typescript 에서 type 과 interface 는 매우 혼용하기 쉬운 타입 선언 방식이며, 나 역시 그러하다. 많은 훌륭하신 분들이 말씀하시듯 하나로 통일하는 것이 좋고 대게 그 선택의 영광은 interface 에게 주어지는데 이는 구조적으로도(확장에 extends 등을 활용하여 &를 사용하는 type 보다 낫기 때문에), 성능적으로도(recursive 를 거치지 않는 선언 방식이기 때문에) 옳은 판단이고 지당하시다고 생각한다.
이 말씀을 따라 일을 할 때 최대한 type을 배재하고자 했으나 어느새 적게나마 type을 사용하고 있는 자신을 발견할 수 있다. 왜 그러한가?
주의: 해당 코드와 논리는 모두 저의 경험에 따라 작성되었습니다. 틀렸을 수도 있습니다.
// interface 는 이런거 안돼
type APIMethodForType = 'GET' | 'DELETE' | 'PUT' | 'PATCH'
// 사실 돼
interface APIMethodForInterface {
POST: 'POST'
GET: 'GET'
DELETE: 'DELETE'
PATCH: 'PATCH'
}
const fetchForSomething = (apiMethod: APIMethodForType) => {}
// 굳이?
const fetchForSomething2 = (apiMethod: keyof APIMethodForInterface) => {}
interface 는 객체 형식으로만 선언이 가능하기 떄문에 객체 형식이 아닌 파라미터 타입 선언이 불편하다. keyof 를 활용하는 방법이 있지만 일일이 해보니까 보기도 불편하고 굳이.. 라는 생각이 많이 들었다. sorting 방식이나 랭귀지 타입 등 스트링 타입 선언은 빈번하게 일어나며 이 때 enum 이라는 대안이 있기는 하지만 tree-shaking 관점으로 봤을 때 현재 typesciprt 환경 하에선 오히려 union types 사용을 권장한다.
뿐만 아니라 interface 를 보완하는 성격도 가질 수 있다.
interface Bremen {
donkey: Donkey
dog: Dog
cat: Cat
cock: Cock
}
type BremenWhichHasFourLegs = Omit<Bremen, 'cock'>
type BremenWhichHasTwoLegs = Pick<Bremen, 'cock'>
지금 머리속에 생각나는게 브레멘 음악대 밖에 없어서 이런 예시밖에 못들었지만 생각보다 빈번하게 이와 비슷한 방식으로 타입을 짜게 된다. 정말 편-리하다. type은 어쩌면 interface 의 멋짐을 지켜주는 다크나이트 같은 존재가 아닐까?
이외에도 위대한 타입스크립트팀에서 type을 살려두시는 이유가 많겠지만 type 사용 배제를 의식하면서 코딩한 시간 동안 느낀 불편함만 꼽아서 적어보았다. 틀린 점이 있다면 화내지 말고 댓글로 알려주면 감사합니다. 끝!