타입 단언(Assertion), 타입 가드(Guards)

Hyun·2022년 6월 29일
0

typescript

목록 보기
2/3

타입 단언(Assertion)

타입스크립트가 타입 추론을 통해 판단할 수 있는 타입의 범주를 넘는 경우, 즉 타입추론으로는 해결할 수 없는 경우, 에러가 발생하는 것을 막기 위해 사용자가 임의로 타입을 명시할 수 있다. 이를 타입 단언이라고 한다.

아래의 예제는 isNumber 가 true 라면 val 의 타입이 number 라는 것을 의미하는걸 알 수 있다. 하지만 타입스크립트는 아직 val 의 타입이 string 또는 number 중에 선택되지 않았으므로 val.toFixed(2) 함수를 실행하는 것을 옳지 않다라고 판단하여 에러를 발생시킨다.(*isNumber 가 true 면 number 타입이라는 것은 사용자들끼리 정한 임의의 약속이므로)

function someFunc(val: string | number, isNumber: boolean) {
  // some logics
  if (isNumber) {
    val.toFixed(2); // 에러 발생- TS2339: ... Property 'toFixed' does not exist on type 'string'.
  }
}

따라서 에러가 발생하는 것을 방지하기 위해 isNumber 가 true 일때 val 이 숫자임을 타입스크립트에게 단언해주어야 한다. 이때 2가지 방식으로 단언할 수 있다.

두번째 방식(<number>val) 은 JSX 를 사용하는 경우 특정 구문 파싱에서 에러가 발생할 수 있으므로 .tsx 파일에서는 사용할 수 없다.

  function someFunc(val: string | number, isNumber: boolean) {
    // some logics
    if (isNumber) {
      // 1. 변수 as 타입
      (val as number).toFixed(2);// 에러 발생 X
      // Or
      // 2. <타입>변수
      // (<number>val).toFixed(2);
    }
  }

타입 가드(Guards)

아래 예제와 같이 타입 단언을 여러 번 하게 될 경우기 존재한다.

function someFunc(val: string | number, isNumber: boolean) {
  if (isNumber) {
    (val as number).toFixed(2);
    isNaN(val as number);
  } else {
    (val as string).split('');
    (val as string).toUpperCase();
    (val as string).length;
  }
}

타입 가드를 사용하면 타입스크립트가 추론 가능한(우리가 타입가드를 통해 지정한) 특정 범위(scope) 에서 타입을 보장할 수 있다.

타입 가드가 return 하는 boolean 값이 true 라면 val is number 가 적용되어 타입 가드가 사용된 곳의 하위 코드들에게 val 의 타입이 number 로 보장된다. 반환 타입의 NAME is TYPE 형태는 타입 술부(Predicate) 라고 부른다.

// 타입 가드 ↓
function isNumber(val: string | number): val is number {
  return typeof val === 'number';
}
// 사용 예제
function someFunc(val: string | number) {
  if (isNumber(val)) {// 타입 가드로 val 이 number 타입인지 검사하고, 맞으면 하위 코드들에게 val 의 타입이 number 임을 보장한다.
    val.toFixed(2);
    isNaN(val);
  } else { // number 타입이 아니므로 자동으로ing 타입이 된다.
    val.split('');
    val.toUpperCase();
    val.length;
  }
}

위 방식말고도 사용가능한 타입 가드가 더 있다. typeof, in, instanceof 등의 연산자를 직접 사용하는 타입 가드들이다. 따로 타입 가드를 함수로 생성할 필요없이, 연산자를 바로 사용하면 된다.

// 1. typeof 
function someFuncTypeof(val: string | number) {
  if (typeof val === 'number') {
    val.toFixed(2);
    isNaN(val);
  } else {
    val.split('');
    val.toUpperCase();
    val.length;
  }
}

// 2. in
function someFuncIn(val: any) {
  if ('toFixed' in val) {
    val.toFixed(2);
    isNaN(val);
  } else if ('split' in val) {
    val.split('');
    val.toUpperCase();
    val.length;
  }
}

[참고 및 출처]
HEROPY Tech 한눈에 보는 타입스크립트

profile
better than yesterday

0개의 댓글