IT일상

타입스크립트 Discriminated Unions

  • 프론트엔드
Profile picture

Written by solo5star

2023. 3. 27. 16:13

type Dog = {
  name: string;
  age: number;
};

type PendingState = {
  dogName: string;
};

type FulfilledState = {
  dog: Dog;
};

type RejectedState = {
  dogName: string;
};

type State = PendingState | FulfilledState | RejectedState;

네트워크로 부터의 응답에 대한 상태를 타입으로 표현해보았습니다. 그럼 State 타입의 값이 주어질 때 이것이 Pending인지, Fulfilled인지, Rejected인지는 어떻게 구분할 수 있을까요?

function processState(state: State) {
  if ('dogName' in state) {
    state; // PendingState | RejectedState
  }
  else if ('dog' in state) {
    state; // FulfilledState
  }
}

각 타입만이 가지는 고유한 속성이 있는지 확인하여 Type Narrowing을 해야 합니다.

하지만 PendingStateRejectedState는 동일한 속성을 가지고 있기 때문에 pending인지, rejected인지 확인할 수 없습니다.

만약 State에 다른 타입이 Union으로 추가되었을 때, 기존의 속성과 공통되지 않을 것이라는 보장이 있을까요?

Discriminated Unions

Tagged Unions 라고도 합니다

구분 가능한 유니온 으로 해석할 수 있습니다.

간단히 설명하자면 유니온을 구분하기 위한 필드를 추가하는 것입니다.

type Dog = {
  name: string;
  age: number;
};

type PendingState = {
  type: "pending";
  dogName: string;
};

type FulfilledState = {
  type: "fulfilled";
  dog: Dog;
};

type RejectedState = {
  type: "rejected";
  dogName: string;
};

type State = PendingState | FulfilledState | RejectedState;

각 상태에 type이라는 필드를 추가하고 String Literal Type을 넣어주었습니다. 만약 PendingState로 Type Narrowing을 한다면, state.type === 'pending' 으로 Narrowing할 수 있습니다.

function processState(state: State) {
  if (state.type === "pending") {
    state; // PendingState
  } else if (state.type === "fulfilled") {
    state; // FulfilledState
  } else if (state.type === "rejected") {
    state; // FulfilledState
  }
}

유니온의 각 타입을 구분하는 type 이라는 프로퍼티만 서로 다르게 가지면 되기 때문에, 서로 중복될 일도 없을 것입니다.

참고 자료


Profile picture

Written by solo5star

안녕하세요 👋 개발과 IT에 관심이 많은 solo5star입니다

  • GitHub
  • Baekjoon
  • solved.ac
  • about
© 2023, Built with Gatsby