TypeScript는 structural typing(구조적 타이핑, "duck typing")을 사용합니다. 두 타입은 이름이나 선언된 위치와 무관하게 **동일한 형태(shape)**를 가지면 호환됩니다. 이는 호환성이 선언된 타입 이름에 따라 결정되는 nominal(명목적) 타이핑(Java, C#)과 대비됩니다.
ts
{ : ; : ; }
() { .(p., p.); }
obj = { : , : , : };
(obj);
TypeScript는 structural typing(구조적 타이핑, "duck typing")을 사용합니다. 두 타입은 이름이나 선언된 위치와 무관하게 **동일한 형태(shape)**를 가지면 호환됩니다. 이는 호환성이 선언된 타입 이름에 따라 결정되는 nominal(명목적) 타이핑(Java, C#)과 대비됩니다.
{ : ; : ; }
() { .(p., p.); }
obj = { : , : , : };
(obj);
obj는 Point로 선언된 적이 없지만, shape를 구조적으로 만족하기 때문에 허용됩니다. 이미 존재하는 변수를 전달할 때는 추가 프로퍼티가 허용됩니다.
print({ x: 1, y: 2, z: 3 }); // ❌ 오류: 'z'는 'Point' 타입에 존재하지 않음
직접 전달되는 객체 리터럴은 오타를 잡기 위해 더 엄격한 "초과 프로퍼티 검사(excess property check)"를 받습니다. 하지만 먼저 변수에 할당하면 통과합니다. 이는 유연성과 실수 방지 사이의 의도적인 균형입니다.
Structural typing은 TypeScript를 유연하고 사용하기 편하게 만듭니다. interface를 명시적으로 구현하지 않고도 만족시킬 수 있어, JavaScript의 객체 리터럴 스타일에 잘 맞습니다.
트레이드오프: 개념적으로 무관하더라도 우연히 같은 shape를 공유하는 타입들은 서로 교환 가능합니다(사람들이 nominal과 같은 구분이 필요할 때 branded types를 사용하는 이유입니다).