본문 바로가기
개발/TypeScript

구조적 타이핑(structural typing)

by 안뇽! 2023. 9. 5.
반응형

구조적 타이핑(structural typing)

자바스크립트는 덕 타이핑 기반이고 타입스크립트는 자바스크립트를 모델링하기 위해 구조적 타이핑을 사용한다.

타입스크립트의 구조적 타이핑을 이야기하려면 먼저 덕 타이핑을 알아야 한다.

덕 타이핑

덕 타이핑을 설명하기 위해 극단적인 예시를 들자면

어떤 새가 오리처럼 울고, 오리처럼 날면 오리라고 생각하는 것이다. 발이 3개더라도

구조적 타이핑 예시

구조적 타이핑은 구조와 정의에 따라 결정되는 타입 시스템인데, 요약하면 덕 타이핑으로 이해해도 된다.

어떤 새가 오리처럼 울고, 오리처럼 날면 오리라고 생각하는 것이다.
발이 3개더라도

위 문장을 생각한채로 아래 코드를 보자.

interface NormalBirdType {
  sound: string;
  wings: string;
}

const isNormalBird = (bird: NormalBirdType) => {
  console.log(bird.sound.length > 0 && bird.wings.length > 0);
  return bird.sound.length > 0 && bird.wings.length > 0;
};

const bird1 = { sound: "꽦꼬ㅒㄲ", wings: "하얀색이고 2개" };

isNormalBird(bird1); // true

const bird3legs = { sound: "꽦꼬ㅒㄲ", wings: "하얀색이고 2개", legs: 3 };
// legs는 신경쓰지 않음.
isNormalBird(bird3legs); // true

어떤 새가 오리처럼 울고, 오리처럼 날면 오리라고 본다. 발이 3개라도
bird3legs의 속성중에 sound: string, wings: string 를 만족하면 NormalBirdType으로 본다. legs의 속성과는 무관하게

구조적 타이핑 관점에서 sound와 wings가 있기 때문에 bird3legs는 NormalBirdType과 호환되어 hiBird의 매개변수로 사용할 수 있다.

 

=> 즉, 기대하는 속성만 만족을 하면 더 많은 속성을 사용해도 문제가 되지 않는다.

구조적 타이핑 문제점

위 예시에서 구조적 타이핑에 의해 sound와 wings만 만족하면 외부의 다른 속성은 고려하지 않게 된다.

아래 코드에서 legs는 타입 체커가 문제로 인식하지 않는다.

interface NormalBirdType {
  sound: string;
  wings: string;
}

const isNormalBird = (bird: NormalBirdType) => {
  console.log(bird.sound.length > 0 && bird.wings.length > 0);
  return bird.sound.length > 0 && bird.wings.length > 0;
};

const bird3legs = { sound: "꽦꼬ㅒㄲ", wings: "하얀색이고 2개", legs: 3 };

// true이면 안되는데 true임
const 날개_빼면_다리만_두개_남는가 = isNormalBird(bird3legs);

날개_빼면_다리만_두개_남는가 에서 isNormalBird(bird3legs)는 false를 반환해야 하지만 하지만 true를 반환한다.

 

이를 해결하기 위해서는 런타임에서의 타입체크나 명시적인 타입체크가 필요하다.(타입스크립트는 런타임에서 사라진다)

const isNormalBird = (bird: NormalBirdType) => {
  const allowedKeys = ["sound", "wings"];
  
  // sound,wings외에도 다른 속성이 있으면 return false
  for (const key in bird) {
    if (!allowedKeys.includes(key)) {
      return false;
    }
  }

  return bird.sound.length > 0 && bird.wings.length > 0;
};

const bird3legs = { sound: "꽦꼬ㅒㄲ", wings: "하얀색이고 2개", legs: 3 };
isNormalBird(bird3legs);

const 날개_빼면_다리만_두개_남는가 = isNormalBird(bird3legs); // false

 

반응형