IT일상

타입스크립트 Discriminated Unions 본문

프론트엔드

타입스크립트 Discriminated Unions

solo5star 2023. 3. 27. 16:13
리뉴얼 된 블로그로 보기: https://solo5star.dev/posts/32/

 

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을 해야 합니다.

 

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

 

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

 

 

Discriminated 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 이라는 프로퍼티만 서로 다르게 가지면 되기 때문에, 서로 중복될 일도 없을 것입니다.

 

 

참고 자료

* https://m.blog.naver.com/mym0404/221800393600

Comments