[Typescript] 타입 좁히기 Type Narrowing

Bam·2023년 8월 28일
0

Typescript

목록 보기
18/32
post-thumbnail

타입 좁히기(Type Narrowing)는 예전에 unknown 타입을 다루면서 언급만 했었는데 타입 좁히기가 무엇이고 어떤 일을 하는지 이번 포스트에서 알아보도록 하겠습니다.


타입 좁히기 Type Narrowing

아래와 같은 함수가 존재할 때, 타입스크립트는 변수 xnumber인지 string인지 확실하게 알 수 없으므로 에러를 발생시킵니다.

const foo = (x: number | string): void => {
  x.toString(2); //Error!!
  x.split(''); //Error!!
}; 

이런 상황에서 각 상황에 맞는 메소드를 사용하고 싶다면 다음과 같이 코드를 수정해야합니다.

const foo = (x: number | string): void => {
  if (typeof x === 'number') {
    x.toString(2);
  }
  if (typeof x === 'string') {
    x.split('');
  }
}; 

if구문을 통해 x타입을 보장하여 메소드 사용과정에서 발생하는 오류를 없앨 수 있습니다. 이때 첫 번째 조건문에서는 x가 number 타입으로 보장되고, 두 번째 조건문에서는 x가 string타입으로 보장됩니다.

이렇게 타입이 보장되면 그 이후로는 보장된 타입으로 자동적으로 변경되며 이것을 타입 좁히기(Type Narrowing)라고 합니다.

타입스크립트는 else문도 대응하므로 if 문 하나를 통해 타입 하나를 좁히면 else 문에서는 if 문으로 좁힌 타입이 될 수 없게됩니다.

const foo = (x: number | string): void => {
  if (typeof x === 'number') {
    x.toString(2);
  }
  else { //if문에서 number가 아니었으므로 당연히 x는 string 타입이 된다고 타입을 좁힌다.
    x.split('');
  }
}; 

타입 가드 Type Guard

if (typeof x === 'number')

위의 코드 처럼 조건문 iftypeof를 통해서 타입 좁히기를 하게 만들어주는 표현식을 타입 가드(Type Guard)라고 부릅니다.

타입 가드는 typeof 말고도 여러가지 표현식을 사용해서 만들 수 있습니다. 타입 가드를 수행하는 대상이 객체인지 변수인지 등에 따라서 사용하는 연산자만 다르고 사용방법은 비슷합니다.

typeof

typeof는 예제 코드에서 봐았던 방식으로 타입 가드를 만들어줍니다. if와 같은 조건문과 함께 사용해 타입 가드를 만들 수 있습니다.

if (typeof x === 'number') {}
if (typeof x === 'string') {}

instanceof

instanceofA instanceof B에서 A 객체가 B 클래스의 인스턴스인지를 판별하는 연산자입니다. 간단히 말해 A가 B에 속하는지를 판별해주는 연산자라고 생각하면 됩니다.

class A {
  x = 'hello';
}
class B {
  y = 'hi';
}

const foo = (arg: A | B) => {
  if (arg instanceof A) {
    console.log(arg.x);
  }
  if (arg instanceof B) {
    console.log(arg.y);
};

in

in 연산자는 객체에 프로퍼티가 존재하는지 확인합니다. 객체의 프로퍼티를 가지고 타입 좁히기를 하고싶은 경우 사용합니다.

type A = {
  x: string;
};
type B = {
  y: string;
};

const foo = (arg: A | B) => {
  if ('x' in arg) {
  //arg에 x라는 프로퍼티가 존재하면 param A 객체로 타입 좁히기
  }
};

리터럴

리터럴 값은 비교 연산자 ===, ==, !==, !=를 사용하여 타입 가드를 만들 수 있습니다.

type X = 0 | 1;

const foo = (arg: X) => {
  if (arg === 0) {
  }
  else if (arg === 1) {
  }
};

0개의 댓글