(TS) Type Guard

Mirrer·2022년 12월 27일
0

TypeScript

목록 보기
11/14
post-thumbnail

Type Guard

컴파일러가 타입을 예측할 수 있도록 타입을 좁혀(narrowing) type safety 방식을 보장

Type Guard는 데이터의 타입을 알 수 없거나, 될 수 있는 타입이 여러 개라고 가정할 때 조건문을 통해 데이터의 타입을 좁혀나가는 것이다.

Type Guard로 인해 아래와 같은 장점을 얻을 수 있다.

  • 데이터의 타입에 따라 대응하여 에러를 최소화
  • 타입을 통해 '가드'하는 코드, 방어적인 코드를 작성

Type Guard에서 사용되는 built-in 연산자 종류는 다음과 같다.


TypeOf

TypeScriptJavaScripttypeof 연산자를 이해할 수 있다.

즉, 조건문에 typeof를 사용하면, TypeScript는 해당 조건문 블록 내에서 해당 변수 타입이 다르다는 것(=좁혀진 범위의 타입)을 이해할 수 있다.

function doSomething(x: number | string) {
  if (typeof x === 'number') {   
    console.log(x.toString());
  }
  x.substr(1); // Error, `x`는 `string`이라는 보장이 없다.
}

InstanceOf

TypeScript는 위의 typeof와 마찬가지로 instanceof 연산자 또한 이해할 수 있다.

이를 통해 if문 으로 타입을 하나 좁혀나가면, else문 안의 변수 타입은 절대 동일한 타입이 될 수는 없음을 인지한다.

class Delveloper {
  name = 'dev';
}

class Person {
  age = 10;
}

function doSomething(arg: Delveloper | Person) {
  if (arg instanceof Delveloper) {
    console.log(arg.name);
    console.log(arg.age); // Error!
  }
  else {
    console.log(arg.name); // Error!
    console.log(arg.age);
  }
}

In

in 은 객체 내부에 특정 property 가 존재하는지 확인하는 연산자로 Type Guard로 활용할 수 있다.

interface A {
  x: number;
}
interface B {
  y: string;
}

function doStuff(q: A | B) {
  if ('x' in q) {
    // q: A
  }
  else {
    // q: B
  }
}

Literal Type Guard

Literal 값의 경우 ===, ==, !==, != 연산자를 이용하여 타입을 구분할 수 있다.

이는 union 타입에 리터럴 타입이 있는 경우에도 동일하게 적용되며, union 타입의 공통 property 값을 비교union 타입을 구분할 수 있다.

type Delveloper = { // 리터럴 타입
  name: 'dev', 
  skill: string
}

type Person = { // 리터럴 타입
  name: 'mirrer', 
  age: number
}

function doSomething(arg: Delveloper | Person) {
  if (arg.name === 'dev') {
  console.log(arg.skill);
  console.log(arg.age); // Error
  }
  else {  
  console.log(arg.skill); // Error!
  console.log(arg.age);
  }
}

StrictNullChecks(null, undefined)

TypeScript== null, != null의 식으로 nullundefined 모두 걸러낼 수 있다.

function doSomething(a?: number | null) {
  if (a == null) return;
  // a는 number
}

사용자 정의 Type Guards

JavaScript 언어는 풍부한 런타임 내부 검사(=runtime introspection support)를 지원하진 않는다.

하지만 TypeScript에서는 사용자 정의 Type Guard 함수를 만들어 이를 해결할 수 있다.

// 일반적인 Interface
interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
  age: number;
}

// 사용자 정의 Type Guard
function isPerson(arg: any): arg is Person {
  return arg.age !== undefined;
}

// 사용자 정의 Type Guard 사용
function doSomething(arg: Developer | Person) {
  if (isPerson(arg)) {
    console.log(arg.age);
    console.log(arg.skill); // Error
  } else {
    console.log(arg.age); // Error
    console.log(arg.skill);     
  }
}

doSomething({ name: 'name', skill: 'typescript' });
doSomething({ name: 'name', age: 123 });

참고 자료

TypeScript: JavaScript With Syntax For Types.
React TypeScript Tutorial for Beginners - Codevolution
타입스크립트 입문 - 기초부터 실전까지 - 장기효

profile
memories Of A front-end web developer

0개의 댓글