개발 일기

Unions and Intersection Types ? 본문

컴퓨터 언어/Typescript

Unions and Intersection Types ?

이건욱

가끔 함수 안에서 매개변수를 넘길 때 string 혹은 number을 원할 때 다음과 같이 구현이 가능합니다.

/**
 * Takes a string and adds "padding" to the left.
 * If 'padding' is a string, then 'padding' is appended to the left side.
 * If 'padding' is a number, then that number of spaces is added to the left side.
 */
function padLeft(value: string, padding: any) {
  if (typeof padding === "number") {
    return Array(padding + 1).join(" ") + value;
  }
  if (typeof padding === "string") {
    return padding + value;
  }
  throw new Error(`Expected string or number, got '${padding}'.`);
}

padLeft("Hello world", 4); // returns "    Hello world"

 

위에 예제에서는 padding 타입이 any이기 때문에 아무값이 넣을수가 있습니다.

// passes at compile time, fails at runtime.
let indentedString = padLeft("Hello world", true);

 

하지만 다음은 Any 타입이기 때문에 모든값이 들어가기 때문에 그 때 우리는 Union Type을 사용할수가 있습니다.

/**
 * Takes a string and adds "padding" to the left.
 * If 'padding' is a string, then 'padding' is appended to the left side.
 * If 'padding' is a number, then that number of spaces is added to the left side.
 */
function padLeft(value: string, padding: string | number) {
  // ...
}

let indentedString = padLeft("Hello world", true);
Argument of type 'true' is not assignable to parameter of type 'string | number'.

Union Type은 다음과 같이 여러타입중에 하나를 의미 합니다. "|" 을 통해서 구분할수가 있습니다. 

 

따라서 위와 같은 경우에는 string or number만 가능합니다.

하지만 Union 타입으로 값을 넘길 경우 파라미터로 넘기는 값들에 대해서 전부다 공통적으로 사용할려는 값들을 가지고 있어야합니다.

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

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

declare function getSmallPet(): Fish | Bird;

let pet = getSmallPet();
pet.layEggs();

// Only available in one of the two possible types
pet.swim();
Property 'swim' does not exist on type 'Bird | Fish'.
  Property 'swim' does not exist on type 'Bird'.

위와 같이 fly() , swim() 은 공통적으로 가지고 있지 않기 때문에 사용이 불가합니다.

 

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;

일반적으로 접근을 할때에는 공통적인 값들 밖에 접근을 못하지만 위에서는 state을 통해서 타입을 구별을 할수가 있습니다. 

그래서 switch문으로 다음과 같이 접근이 가능합니다.

type NetworkState =
  | NetworkLoadingState
  | NetworkFailedState
  | NetworkSuccessState;

function networkStatus(state: NetworkState): string {
  // Right now TypeScript does not know which of the three
  // potential types state could be.

  // Trying to access a property which isn't shared
  // across all types will raise an error
  state.code;
Property 'code' does not exist on type 'NetworkState'.
  Property 'code' does not exist on type 'NetworkLoadingState'.

  // By switching on state, TypeScript can narrow the union
  // down in code flow analysis
  switch (state.state) {
    case "loading":
      return "Downloading...";
    case "failed":
      // The type must be NetworkFailedState here,
      // so accessing the `code` field is safe
      return `Error ${state.code} downloading`;
    case "success":
      return `Downloaded ${state.response.title} - ${state.response.summary}`;
  }
}

 

또한 다음과 같이 '&'을 통해서 하나의 타입이 다음과 같이 두개의 타입을 가지고 있습니다.

interface ErrorHandling {
  success: boolean;
  error?: { message: string };
}

interface ArtworksData {
  artworks: { title: string }[];
}

interface ArtistsData {
  artists: { name: string }[];
}

// These interfaces are composed to have
// consistent error handling, and their own data.

type ArtworksResponse = ArtworksData & ErrorHandling;
type ArtistsResponse = ArtistsData & ErrorHandling;

const handleArtistsResponse = (response: ArtistsResponse) => {
  if (response.error) {
    console.error(response.error.message);
    return;
  }

  console.log(response.artists);
};

'컴퓨터 언어 > Typescript' 카테고리의 다른 글

Generics ?  (0) 2020.05.14
Enums ?  (0) 2020.05.12
Literal Types ?  (0) 2020.05.03
Function ?  (0) 2020.05.03
Class ?  (0) 2020.05.01
Comments