본문으로 건너뛰기

아이템4

구조적 타이핑에 익숙해지기

타입스크립트 컴파일러의 역활

  • 자바스크립트는 본질적으로 덕 타이핑(매개변수 값이 모두 제대로 주어진다면, 그 값이 어떻게 만들어졌는지 신경 쓰지 않고 사용) 기반이다.
interface Vector2D {
x: number;
y: number;
}

function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
  • 위 예제서 name이 추가된 새 인터페이스가 생성되어도 타입스크립트에서 함수 호출이 가능하다.
interface NamedVector2D {
name: string;
x: number;
y: number;
}

function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
  • NamedVector2DVector2D의 관계를 전혀 선언하지 않았음에도 함수는 실행되었다.
  • 이유는 타입스크립트의 타입이 자바스크립트 런타임 동작에 모델링하기 떄문이고 이에 따라 둘의 구조가 호환되며 이를 구조적 타이핑이라 칭한다.
  • 다만 이로인해 문제가 발생하기도 한다.
interface Vector3D {
x: number;
y: number;
z: number;
}

function nomallize(v: Vector3D) {
return {x:v.x, y:v.y; z:v.z}
}
  • 위와 같은 인터페이스가 존재할 때 z가 정규화 과정에서 무시되었고 타입 체커는 이 문제를 잡아내지 못한다.
  • 이는 함수 작성시 호출에 사용되는 매개변수 속성들이 매개변수 타입에 선언된 속성만을 가질 것이라 생각하기 때문이다. 이러한 타입은 봉인된타입 또는 정확한 타입이라고 명명한다.

구조적 타이핑의 클래스에서의 문제

class C {
foo: string;
constructer(foo: string) {
this.foo = foo;
}
}
const c = new C("instace of C");
const d = { foo: "object literal" };
  • d는 string 타입의 foo 속성을 가지게 된다. 또한 호출이 되는 생성자를 가짐으로 문제가 생기지 않는다. 만일 C의 생성자에 단순 할당이 아닌 연산 로직이 존재한다면 d의 경우 문제가 발생한다.

요약

  • 자바스크립트는 덕 타이핑이고 타입스크립트가 이를 모델링하기 떄문에 구조적 타이핑을 사용한다.
  • 타입은 개방되어 있다.
  • 클래스 역시 구조적 타이픙의 규칙을 따른다.
  • 구조적 타이핑을 이용하면 유닛 테스를 쉽게 적용할 수 있다.