chap.7 연산자 타입

유원근·2020년 12월 24일
0
post-thumbnail

인터섹션 (Intersection)

Intersection타입은 말 그대로 여러타입이 합쳐진 하나의 타입을 말합니다.

두개의 Interface타입의 인자를 전달받아 하나의 객체로 합쳐주는 함수를 만들어주세요.

interface User {
  name: string;
}
interface Action {
  do(): void;
}

function createUserAction(u: User, a: Action):{무엇이 반환?} {
  return {...u, ...a};
}

이런 경우에 함수의 반환값을 무엇으로 지정해 주어야 할까요? 바로 Intersection을 사용해주면 됩니다.

User & Action이런식으로 &기호를 이용해 두가지 타입을 합쳐줄 수 있습니다.

function createUserAction(u: User, a: Action): User & Action {
  return {...u, ...a};
}

만들어진 함수를 사용해보면 다음과 같이 타입이 적용된 것을 확인할 수 있습니다.

이렇게 Intersection을 사용하면 기존타입을 이용한 상속과 같은걸 사용하지 않고 간단하게 사용할 수 있습니다.


유니온 (Union)

만약 인자 두개를 받아서 비교를 해주는 함수를 만들고 싶다면 어떻게 구현해야 할까요?

function compare(x: string, y: string): boolean {
  if (x === y) {
    return true;
  } else {
    return false;
  }
}

이렇게 사용해줄 수 있겠죠?

하지만 인자로 문자뿐만 아니라, 숫자도 넣어주고 싶다면 다음과 같이 유니온 타입을 통해 간단히 구현할 수 있습니다.

function compare(x: string | number, y: string | number): boolean {
  if (x === y) {
    return true;
  } else {
    return false;
  }
}

위와같이 |를 이용해 두가지 모두 들어올수 있도록 만들어주는 것을 유니온타입이라고 합니다.
또한 문자와 문자 숫자와 숫자를 비교하고 싶다면 typeof를 이용해서 타입가드를 사용해주면됩니다.

function compare(x: string | number, y: string | number): boolean {
  if (typeof x === "number" && typeof y === "number") {
    return x === y ? true : false;
  }
  if (typeof x === "string" && typeof y === "string") {
    return x.localeCompare(y) ? true : false;
  }
}

또한 문자와 문자 / 숫자와 숫자 만 입력받게끔 해주기 위해 함수시그니처 오버로딩을 사용할 수 있습니다.

function compare(x: number, y: number): boolean;
function compare(x: string, y: string): boolean;
function compare(x: string | number, y: string | number): boolean {
  if (typeof x === "number" && typeof y === "number") {
    return x === y ? true : false;
  }
  if (typeof x === "string" && typeof y === "string") {
    return x.localeCompare(y) ? true : false;
  }
}

다음과 같이 문자/숫자를 혼용하면 에러가 나오는 것을 볼 수 있습니다.

원시타입이 아닌 타입의 유니온

위에서 작성한 User , Action인터페이스중 하나의 타입을 인자로 받는 함수를 만들어 보아요.

interface User {
  name: string;
}
interface Action {
  do(): void;
}
function process(v: User | Action) {}

이런 경우에 함수안에서 vUser인지 Action인지 어떻게 알 수 있을까요
함수 안에서 if문을 통해 인터페이스 안에 있는 do메소드가 있는지 확인해 보겠습니다.

function process(v: User | Action) {
    if(v.do)
}

아래와 같이 do는 User와 Action의 공통된 타입이 아니기 때문에 에러가 나오는 것을 확인할 수 있습니다.

Type Assertions (타입어설션)

이런 경우에는 아래와 같이 Type Assertions (타입어설션)을 통해 타입이 Action이라고 가정해 줄 수 있습니다.

function process(v: User | Action) {
    if((<Action>v).do){
        (<Action>v).do
    }
}

Type Assertions (타입어설션)은 개발자가 타입스크립트에게 지금 뭘 하고 있는지 말해주는 것으로 볼 수 있습니다.

하지만 매번 이렇게 타입가드를 해줄 수는 없으니 직접 개발자가 타입가드를 만들어 사용해 줄 수 있습니다.

사용자 정의 타입가드

function isAction(v: User | Action): v is Action {
  return (<Action>v).do !== undefined;
}

v를 인자로 받은후 만약 v.do가 존재한다면 vAction 이다. 라고 하는 코드입니다.
이를 적용해서 위 코드를 다시 작성해 본다면 아래와 같습니다.

function isAction(v: User | Action): v is Action {
  return (<Action>v).do !== undefined;
}
function process(v: User | Action) {
  if (isAction(v)) {
    v.do;
  } else {
    v.name;
  }
}

유니온 타입을 사용했을 경우에는 꼭 타입가드를 사용해서 안전한 코딩을 해요!

0개의 댓글