타입스크립트 덕 타이핑과 구조적 타이핑
자바스크립트는 본질적으로 “덕 타이핑” 기반으로 사용자는 타입이 무엇인지 신경쓰지 않게 합니다. 그리고 타입스크립트는 이를 “구조적 타이핑” 기반으로 모델링합니다. 따라서 덕 타이핑과 구조적 타이핑을 이해하지 못한다면 예상하지 못한 결과와 마주할 수 있습니다. 이 두 타이핑을 이해해보도록 합시다.
덕 타이핑 (Duck Typing)
만약 어떤 함수의 매개변수 값이 모두 제대로 주어진다면, 그 값이 어떻게 만들어졌는지 신경 쓰지 않고 사용합니다. 이 말이 조금 어렵게 느껴진다면 덕 타이핑은 아래의 문구로 쉽게 이해할 수 있습니다.
“만약 어떤 새가 오리처럼 걷고, 헤엄치고, 꽥꽥거리는 소리를 낸다면, 나는 그 새를 오리라고 부를 것이다.”
어떤 새가 오리로 태어났는지, 정말 오리인지는 중요하지 않습니다. 새가 오리처럼 보이고 오리처럼 행동하면 오리가 아닐리가 없다고 생각하는 것 바로 그것이 “덕 타이핑"입니다.
예시
interface Lion {
age: number;
sounds: string;
}
interface Cat {
age: number;
sounds: string;
favorite: 'mouse' | 'tuna' | 'chur';
}
const simba: Lion = {
age: 10,
sounds: 'roar',
};
const jerry: Cat = {
age: 6,
sounds: 'meow',
favorite: 'chur'
}
function introduceLion({ age, sounds }: Lion): string {
return `This lion is ${age} years old and sounds like ${sounds}`;
}
console.log(introduceLion(simba));
// "This lion is 10 years old and sounds like roar"
console.log(introduceLion(jerry));
// "This lion is 6 years old and sounds like meow"
introduceLion
함수는 Lion
타입을 매개변수로 받아 사자에 대한 소개글(string
)을 반환하는 함수이다. 따라서 Lion
타입인 simba
를 매개변수로 받을 때만 실행되어야할 것 같지만, Cat
타입인 jerry
를 매개변수로 받아도 실행되는 것을 볼 수 있습니다.
함수를 작성할 때, 매개변수의 속성들이 매개변수의 타입에 선언된 속성만을 가질거라 생각하기 쉽습니다. 이러한 타입은 “봉인된 타입(Sealed Type)” 혹은 “정확한 타입(Precise Type)”이라고 불리며, 타입스크립트에서는 표현할 수 없습니다.
구조적 타이핑 (Structural Typing)
타입스크립트도 역시 덕 타이핑을 그대로 모델링합니다. 하지만 정적 타이핑 언어인 타입스크립트의 타입 체커가 컴파일 단계에서 타입 검사를 어떻게 하는지 이해도가 사람마다 달라 예상하지 못한 결과가 나오기도 합니다. 구조적 타이핑을 이해한다면 보다 결과를 예측하기 쉬워질 것입니다.
위의 덕 타이핑 예제에서 본 것 처럼 타입스크립트 타입 시스템에서는 봉인된 타입을 표현할 수 없습니다. 타입스크립트의 타입 시스템에서 타입은 타입 확장에 대해 “열려” 있습니다.
구조적 타이핑에서는 introduceLion
의 매개변수의 타입인 Lion
을 이해할 때, Lion
의 속성에 해당하는 값이 값을 넣는 타입에 속성으로 존재하는가로 이해해야 합니다. 명확한 상속관계(A - B)를 지향하는 명목적 타이핑과 다르게 구조적 타이핑은 집합으로 포함한다는 개념을 지향하기 때문입니다.
마무리
- 런타임시에는 자바스크립트의 덕 타이핑 특성을 가지고 있고 컴파일시에는 구조적 타이핑을 활용하여 이를 모델링합니다.
- 타입스크립트의 타입 체커는 집합 단위로 체크하기 때문에 중복되는 메서드를 줄일 수 있다는 큰 장점이 존재합니다. 하지만 의도하지 않은 동작을 할 수 있어 이에대한 이해가 필요합니다.
참고자료
- 이펙티브 타입스크립트. 댄 벤더캅.
- 아이템4 구조적 타이핑에 익숙해지기
- https://vallista.kr/덕-타이핑과-구조적-타이핑/