타입 좁히기

타입 좁히기

타입스크립트가 코드를 파악해서 타입을 추론하는 것을 제어 흐름 분석이라 부른다.

  • 제어 흐름 분석은 완벽하지 않다.

  • 다양한 타입 좁히기 방법을 익혀서 사용할줄 알아야 한다.

  • 타입 좁히기는 자바스크립트 문법을 사용해서 진행해야 한다.

// 간단한 null과 undefined 구분
function strOrNullOrUndefined(param: string | null | undefined) {
  if (param === undefined) { // 또는 typeof param === 'undefined'
    param; // undefined
  } else if (param === null) {
    param; // null
  } else {
    param; // string
  }
}
  • 타입 좁히기에 꼭 typeof 를 써야 할 필요가 없다.

  • 타입스크립트도 자바스크립트 문법을 사용하기 때문에 활용

// Array 구분
function strOrNumArr(param: string | number[]) {
  if (Array.isArray(param)) {
    param; // number[]
  } else {
    param; // string
  }
}

// instanceof 연산자 활용 (클래스, 함수)
class A {}
class B {}
function classAorB (param: A | B) {
  if (param instanceof A) {
    param; // A
  } else {
    param; // B
  }
}

두 객체를 구분하는 방법

  • 타입 좁히기는 자바스크립트 문법을 사용해서 진행해야 한다.

  • 즉, 자바스크립트에서도 실행할 수 있는 코드여야 한다.

interface X {
  width: number;
  height: number
}
interface Y {
  length: number;
  center: number;
}
// X, Y는 타입스크립트의 인터페이스이므로 에러가 발생
function objXorY(param: X | Y) {
  if (param instanceof X) {
    param; // error
  } else {
    param;
  }
}
  • 객체의 속성으로 구분하면 될까?

  • in 연산자를 사용

function objXorY(param: X | Y) {
// 자바스크립트에서 유효한 방식이지만, width 속성이 Y에 존재하지 않지만 width 속성에 접근해서 에러 발생
  if (param.width) { // error
    param;
  } else {
    param;
  }
}

// 👍
function objXorY(param: X | Y) {
  if ('width' in param) {
    param; // X
  } else {
    param; // Y
  }
}

브랜드 속성 활용

  • 브랜드 속성이라는 공통 속성이 있으므로 in 연산자 대신 바로 속성에 접근 가능

interface Money {
  _type: 'money';
  amount: number;
  unit: string;
}

interface Liter {
  _type: 'liter';
  amount: number;
  unit: string;
}

function moneyOrLiter(param: Money | Liter) {
  if (param._type === 'money') {
    param; // Money
  } else {
    param; // Liter
  }
}

직접 타입 좁히기 함수 만들어서 사용 (타입 가드)

  • if 문에서 사용하는 함수를 직접 만들면 타입 좁히기가 정상 작동하지 않음

    • 논리적으로는 타입이 구분되어야 하지만 타입스크립트는 구분하지 못한다.

function isMoney(param: Money | Liter) {
  if (param._type === 'money') {
    return true
  } else {
    return false
  }
}

function moneyOrLiter(param: Money | Liter) {
  if (isMoney(param)){
    param; // Money | Liter
  } else {
    param; // Money | Liter
  }
}
  • 타입스크립트가 이해할 수 있게 타입 서술 함수 를 추가로 작업해주어야 한다.

  • is 특수한 연산자를 사용하면 참일 때 매개변수의 타입도 is 뒤에 적은 타입으로 좁혀진다.

    • 좁혀질 타입을 잘못 적는 경우가 생길 수 있으니 주의

  • 최대한 기본적인 타입 좁히기를 먼저 시도하고, 정 안되면 타입 서술을 사

function isMoney(param: Money | Liter): param is Money {
  if (param._type === 'money') {
    return true
  } else {
    return false
  }
}

Predicate는 매개변수 하나를 받아 boolean을 반환하는 함수를 의미한다.

Last updated