ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 타입스크립트의 union type은 수학의 union type과 조금 다르다.
    Type Script 2022. 1. 17. 22:26

    union type은 이 type 혹은 저 type이 올 수 있다는, or 연산자의 개념으로 소개되고 있다.

    수학에서는 합집합으로 표현할 수 있다. 

    A와 B의 합집합이라면 모든 값들에 접근할 수 있어야한다.

    그렇다면 A와 B의 교집합 부분을 제외한 각각의 부분에도 union interface를 선언해주었다면 접근할 수 있을까?

    합집합 - 교집합 부분 (각각의 차집합 부분)

    접근할 수 없다. 그 이유는 다음과 같다. 

    interface Bird {
      fly(): void;
      layEggs(): void;
    }
     
    interface Fish {
      swim(): void;
      layEggs(): void;
    }

    여기 두 개의 interface 가 있다.

    Bird와 Fish는 서로 중복되는 메소드를 가졌고, 다음과 같이 나타낼 수 있다.

    그리고 이 두 개의 interface를 유니언으로 삼는 새로운 function을 선언한다면 

    중복되는 영역 (파랑) 외에도 모든 영역의 메소드를 불러올 수 있어야한다. 

    declare function getSmallPet(): Fish | Bird;
     
    let pet = getSmallPet();
    pet.layEggs();   // 교집합 => 호출가능

    그러나 차집합에 속하는 메소드를 새로 선언한 getSmallPet()에서 호출하면 에러가 나온다.

    pet.swim(); // Does not work.
    // Property 'swim' does not exist on type 'Bird | Fish'.
      // Property 'swim' does not exist on type 'Bird'.

    타입스크립트는 런타임 시점에서 Bird 유형이 올지, Fish 유형이 올지 모르고 있기 때문에

    두 유형이 모두 확실히 갖고 있는 layEggs() 만 에러없이 통과시켜준다. 

    결국 union type(합집합) 이라고 하지만 겹치는 부분이 있다면 intersection(교집합)부분만 통과시켜주는 셈이다.

    교집합 (intersection)

    그렇다면 타입스크립트에게 내가 선언해준 union 에 교집합이 없으니

    언제나 둘 중 한 가지의 타입(Fish interface 혹은 Bird interface)만 올 수 있다고 알려주려면 어떻게 해야할까?

    literal type을 사용해서 각각의 경우를 tagging 해서 확실한 타입을 타입스크립트에게 알려주면 된다. 

    이것을 차별된 유니온타입(discriminating unions)라고 부른다.

     

    type NetworkLoadingState = {
      state: "loading";
    };
    
    type NetworkFailedState = {
      state: "failed";
      code: number;
    };
    
    type NetworkSuccessState = {
      state: "success";
      response: {
        title: string;
        duration: number;
        summary: string;
      };
    };
    
    // Create a type which represents only one of the above types
    // but you aren't sure which it is yet.
    type NetworkState =
      | NetworkLoadingState
      | NetworkFailedState
      | NetworkSuccessState;

    3개의 network와 관련된 type들(NetworLoadingState, NetworkFailedState, NetworkSuccessState) 에는 모두 state가 string의 형식으로 들어있다. 

    따라서 3개의 type들을 NetworkState라는 유니온 타입으로 묶어준 다음 state를 케이스별로 분류, 각각의 interface을 에러없이 사용할 수 있다 .

    function logger(state: NetworkState): string {
    switch (state.state) {
        case "loading":
          return "Downloading...";
        case "failed":
          return `Error ${state.code} downloading`;
        case "success":
          return `Downloaded ${state.response.title} - ${state.response.summary}`;
      }
    }

    출처: Typescriptlang.org

     

    Handbook - Unions and Intersection Types

    How to use unions and intersection types in TypeScript

    www.typescriptlang.org

     

    댓글

Designed by Tistory.