타입스크립트를 이용하여 개발하다 보면 타입을 정의할 때 Type Alias
와 Interface
중 어느 것을 사용해야 할지 고민된다.
Type Alias
와 Interface
의 차이점을 알아보고, 상황에 알맞게 사용해보자.
type TState = {
name: string;
capital: string;
}
interface IState {
name: string;
capital: string;
}
추가 속성을 할당한다면 동일하게 오류가 발생한다.
const wyoming: TState = {
name: "Wyoming",
capital: "Cheyenne",
population: 500000 // 오류 발생
};
인덱스 시그니처를 인터페이스와 타입에서 모두 사용할 수 있다.
type TDict = { [key: string]: string };
interface IDict {
[key: string]: string;
}
함수 타입을 인터페이스나 타입으로 정의할 수 있다.
type TFn = (x: number) => string;
interface IFn {
(x: number) => string;
}
const toStrT : TFn = x => '' + x;
const toStrI : IFn = x => '' + x;
모두 제네릭이 가능하다.
type TPair<T> = {
first: T;
second: T;
}
interface IPair<T> = {
first: T;
second: T;
}
클래스를 구현(implement)할 때, 타입과 인터페이스 둘 다 사용할 수 있다. (이때, 유니온 타입은 사용할 수 없다.)
class StateT implements TState {
name: string = "";
capital: string = "";
}
class StateI implements IState {
name: string = "";
capital: string = "";
}
타입은 인터페이스를 확장할 수 있으며, 인터페이스는 타입을 확장할 수 있다. (이때, 인터섹션 타입을 확장할 수는 있지만, 유니온 타입을 확장하지 못한다.)
type TStateWithPop = IState & { population: number; };
interface IStateWithPop extends TState {
population: number;
}
유니온 타입은 있지만, 유니온 인터페이스는 없다.
type AorB = 'a' | 'b';
타입은 유니온 타입을 확장할 수 있지만, 인터페이스는 유니온 타입을 확장할 수 없다.
type NamedVariable = (Input | Output) & { name: string };
인터페이스는 선언 병합이 가능하지만, 타입에서는 불가능하다.
Interface
가 여러 개 선언되어도 컴파일 시점에 병합되는 것을 말한다.interface IState {
name: string;
capital: string;
}
interface IState {
population: number;
}
const wyoming: IState = {
name: "Wyoming",
capital: "Cheyenne",
population: 500000
};
Typescript 팀은 개방-폐쇄 원칙에 따라 확장에 열려 있는 Javascript 객체와 비슷하게 동작하도록 Interface를 설계했다.
개방-폐쇄 원칙 : 객체를 다룸에 있어서 객체의 확장은 개방적으로, 객체의 수정은 폐쇄적으로 대하는 원칙이다.
그래서 Typescript 팀은 가능한 Type Alias
보다 Interface
를 사용하고, Union Type
혹은 Tuple Type
을 써야 하는 상황이면 Type Alias
를 사용하도록 권장하고 있다.