팀 프로젝트를 TS로 진행하면서 type과 interface에 대한 차이점을 정확히 알고 ts의 장점을 최대한으로 사용하고자 학습 후 해당 글을 작성합니다.
평소 interface와 type을 크게 구분짓지 않고 사용을 해왔다. 같은 팀원분의 코드를 보니 interface와 type의 경계를 구분지어 사용하시는 거 같아. 코드를 보고 그 차이를 알아보았다.
필자도 해당 내용을 학습하여 코드에 적용해보았다.
공통점은 타입을 정의한다는 점이다.(특히 객체의 구조)
가장 큰 차이점은 병합가능성이다.
interface는 병합이 가능하고 type은 병합이 불가능하다.
interface는 동일한 이름으로 여러번 선언할 수 있고 이는 자동으로 병합된다. 즉
interface Dog{
name:string;
}
interface Dog{
age:number;
}
const dog:Dog ={
name:"gamza",
age: 5
}
이게 가능하다. interface는 병합을 통해 일관성을 유지할 수 있다.
type Dog = {
name:string;
}
type Dog = {
age:number;
}
//오류발생!!!
이게 되지 않는다.
정확하게는 "선언병합이 불가능한것이다."
type도 확장은 가능하다.
type Person = {
name: string;
};
type Employee = Person & {
employeeId: number;
};
const emp: Employee = {
name: "Jane",
employeeId: 123
};
이런식으로 확장성은 있지만 재선언으로 타입의 확장을 하는 개념은 아니다.
(interface 역시 extends를 사용하여 확장이 가능하다. + 선언병합까지가능)
즉, interface의 경우 강제성 + 확장성이 좋은 것이다. 재선언을 통해 전역적으로 interface가 병합된다는 점이 가장 큰 차이점이다.
필자가 생각하기로 확장성, 강제성에 유용한 것은 interface이다.
반면 type은 더 넓은 타입 (유니온, 튜플, 리터럴 등)을 정의하는데 사용할 수 있다.
변동성이 높은 데이터 (예를 들어, 사용자 input, API 데이터 props type)같은 경우에는 interface를 사용하는게 좋을 거 같다.
복잡한 타입시스템(제네릭과 같은..)의 경우에는 type을 사용하는게 좋아보인다.
// 일부 코드 중
export interface ClubCreationInputHookI{
clubFutsalOrSoccer: "futsal" | "soccer";
clubImg: File[];
clubAge: string;
clubGender: "남" | "여";
clubFrequentMatchTime: string;
clubPreferredPosition: string;
clubTeamTactics: string;
};
export type ClubFormProps = {
register: UseFormRegister<ClubCreationInputHookI>;
};
로 변경하여 변동성이 있을 확률이 높은 Input의 Type은 interface로 정의해주었고 register만을 담는 Props는 type으로 선언을 해주었다.
(이 부분은 interface를 사용해도 될 거같다.
현재 개발 단계에서는 interface만을 사용해도 커버가 가능하다.
차후에 복잡한 타입(제네릭같은)구조를 사용하게 되면 type을 고려해보겠다.)