interface는 이름 중복이 허용되고,
type은 이름 중복이 불가하다는 차이점만 제외하고 둘은 같도고 보면 된다.
유연한 타입 정의 ★★★
type TOnlyStringValueObject = {
[prop: string]: string;
}
// key가 string 이고: value가 string인 것들
type TOnlyBooleanValueObject = {
[prop: string]: boolean;
}
// key가 string 이고: value가 boolean인 것들}
const randomStringObject: TOnlyStringValueObject = {
k_value: 'K',
o_value: 'O',
r_value: 'R',
e_value: 'E',
a_value: 'A',
}
함수 타입 정의 시 차이 ★★★
// (1) {} brase가 없을 시
type FooFunction1 = (value: string, index?: number) => string;
// (2) {} brase가 있을 시
type FooFunction2 = {
(value: string, index?: number): string;
}
// brase의 차이만 있을 뿐 둘은 같다.
사용 예시
// (가능 : 함수 표현식 (식) ★★★)
const getApi: FooFunction1 = (value, index) => {
return 'success!';
};
// (불가능 : 함수 정의문, 함수 선언문 (문) ★★★) - error
function getApi2(value: string, index: number): FooFunction2 {
return 'success!';
}
함수를 정의하면 사용 시 함수 정의 문에 사용하는 것이 아니라 반드시 함수 표현 식에 사용해야 한다.
생성자 함수 타입 정의
// (1) {} brase가 없을 시
type IRectConstructor1 = new (x: number, y: number) => IRect;
// (2) {} brase가 있을 시
type IRectConstructor = {
new (x: number, y: number): IRect;
}
사용 예시
interface IRect {
id: number;
x: number;
y: number;
weight: number;
height: number;
}
class Rect implements IRect {
id: number;
x: number;
y: number;
weight: number;
height: number;
constructor(x: number, y: number) {
this.id = 1;
this.x = x;
this.y = y;
this.weight = 0;
this.height = 0;
}
}
// 일반적인 정의에는 사용X
const rect = new Rect(0, 0);
// 이렇게 사용 될 때는 함수를 통해 객체의 인스턴스를 생성할 때 정의하여 사용된다.
// 함수를 통핸 생성자 정의 시 사용
function createDefaultRect(cstor: IRectConstructor) {
return new cstor(0, 0);
}
createDefaultRect(Rect);
정리하자면 데이터를 묘사할 땐 타입 Alias를 쓰고
데이터를 포괄하는 객체를 묘사하는 경우에는 인터페이스를 쓴다.
당연히 그리고 클래스를 묘사할 때는
클래스 자체가 데이터와 행위를 포괄하고 있기 때문에 인터페이스를 쓰는 게 훨씬
자연스럽다는 생각을 하게 됩니다.