[TypeScript] 고급타입 : 구별된 유니온(Discriminated Union)

Hoplin·2023년 6월 30일
1
post-thumbnail

구별된 유니온이란, 유니온 타입을 구성하는 타입들의 공통된 "리터럴 타입" 필드를 통해서 구분하는것을 의미한다.

아래와 같이 두개의 인터페이스가 있다고 가정하자.

interface Bird {
  flyingSpeed: number;
}

interface Horse {
  runningSpeed: number;
}

type Animal = Bird | Horse;

그리고 Animal타입 변수를 받아 동물의 속도를 출력하는 함수를 구현한다고 가정한다.

function getAnimalSpped(animal: Animal) {
  console.log(animal.flyingSpeed); // 'Animal' 형식에 'flyingSpeed' 속성이 없습니다.'Horse' 형식에 'flyingSpeed' 속성이 없습니다.
  console.log(animal.runningSpeed); // 'Animal' 형식에 'runningSpeed' 속성이 없습니다.'Bird' 형식에 'runningSpeed' 속성이 없습니다.
}

당연하게도 오류가 난다. Bird 인터페이스에는 runningSpeed가 없으며 Horse에는 flyingSpeed가 존재하지 않기 때문이다. 물론 in을 활용한 TypeGuard를 해줄 수 있지만, 문자열을 하드코딩 해야하므로 발생할 수 있는 위험성은 여전하다.

각각의 BirdHorsetype이라는 속성을 만들고, 리터럴 타입으로 각각 bird,horse로 작성해준다.

interface Bird {
  type: "bird";
  flyingSpeed: number;
}

interface Horse {
  type: "horse";
  runningSpeed: number;
}

이렇게 하게 되면, TypeScript는 공통된 리터럴 타입을 인식하고, 사용자에게 각각의 객체를 리터럴타입을 통해 구분하도록 자동완성을 제공한다. 공통된 type 필드의 리터럴 타입을 통해 Animal타입 객체들간의 TypeGuard를 해줄 수 있다. 그리고 이것이 구별된 유니온의 핵심적 특징이다.

getAnimalSpeed 함수를 switch - case를 통해 아래와 같이 작성해줄 수 있다.

function getAnimalSpped(animal: Animal) {
  let speed: number = 0;
  switch (animal.type) {
    case "bird":
      speed = animal.flyingSpeed;
      break;
    case "horse":
      speed = animal.runningSpeed;
      break;
  }
  console.log(`${animal.type} is moving with speed ${speed}km`);
}

getAnimalSpped({
  type: "bird",
  flyingSpeed: 10,
});
profile
더 나은 내일을 위해 오늘의 중괄호를 엽니다

0개의 댓글