본문 바로가기
프로그래밍 개발/Typescript

Typescript 타입 가드

by Jinseok Kim 2021. 5. 11.
반응형

 

타입 가드

 

타입가드는 자동으로 타입 범위를 좁혀주는 타입스크립트의 기능이다. 생산성과 가독성이 높아지는 효과를 볼 수 있고 as와 같은 극단적인 기능을 쓰지 않아도 된다.

 

 

 

기본 코드

function print(value: number | string){
    if(typeof value === 'number') {
        console.log((value as number).toFixed(2));
    } else {
        console.log((value as string).trim(2));
    }
}
  • 위의 코드에서 as는 타입을 강제로 주입하는 기능으로 어쩔 수 없을때만 사용해야한다. 만약 if 조건문에 number 말고도 string 또한 허용된다면 버그가 생길 위험이 있기 때문이다.
  • 원래 if문을 통해 value의 타입을 정해주어 as을 사용했지만 타입 가드의 기능이 있어 사실 as을 쓰지 않아도 자동으로 value의 타입 값을 if문의 조건에 따라 정해주므로 as을 사용하지 않아도 된다.
  • 즉 이 기능들이 타입 가드라고 불리며 if문의 조건을 볼 수 있는 타입스크립트의 똑똑함이 드러난다.

 

 

class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {}
}
class Product {
    name: string;
    price: number;
    constructor(name: string, price: number) {}
}

function print(value: Person | Product){
    console.log(value.name);
    if(value instanceof Person) {
        console.log(value.age);
    } else {
        console.log(value.price);
    }
}
  • 위와 같이 if문의 instanceof라는 값의 영역에서 사용하는 자바스크립트 기능을 이용하여 value가 class Person의 객체인지 확인하여 value의 타입을 지정해주어 타입 가드의 기능이 발휘하여 자동으로 타입이 지정된다는 것을 알 수 있다.
  • 만약 Person class가 들어온다는 이야기는 value의 age 타입이 들어온다는 이야기이고 아니면 Product class가 들어왔다는 이야기 이므로 price 타입이 들어온다는 것을 확인할 수 있다.

 

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

function print(value: Person | Product){
    console.log(value.name);
    if(value instanceof Person) {
        console.log(value.age); //오류.
    } else {
        console.log(value.price); //오류.
    }
}

하지만 interface는 타입을 지정하기 위한 코드이고 class와 다르게 컴파일 후 사라지는 것이어서 instanceof가 먹히지 않아 오류가 등장해버린다.

 

 

 

 

 

 

discriminated union

interface Person {
    type:'a';
    name: string;
    age: number;
 
}
interface Product {
    type:'b';
    name: string;
    price: number;
  
}

function print(value: Person | Product){
    if(value.type === 'a') {
        console.log(value.age);
    } else {
        console.log(value.price);
    }
}
  • interface을 if문 조건에 걸리게 하는 방법으로 discriminated union라는 것이 있다.
  • interface 마다 type이라는 똑같은 키 이름을 지정하고 타입 값을 서로 다르게 하여 구별하는 것이다.
  • type ='a'을 가지고 있으면 Person의 inerface 이므로 value에는 age 타입이 들어온다는 것을 확인할 수 있다.

 

interface Person {
    type: 'a';
    name: string;
    age: number;
}
interface Product {
    type: 'b';
    name: string;
    price: number;
}

function print(value: Person | Product) {
    switch (value.type) {
        case 'a':
            console.log(value.age);
            break;
        case 'b':
            console.log(value.price);
            break;
    }
}

위에처럼 if문 뿐만 아니라 swich문을 사용하여 interface 각각에 들어있는 type을 이용하여 값의 범위를 구별할 수 있게 되었다. 

 

 

 

 

 

 

interface를 구별하는 기타 방법

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

function isPerson(x: Person | Product): x is Person {
    return (x as Person).age != undefined;
}

function print(value: Person | Product) {
  if( isPerson(value)){
      console.log(value.age)
  } else{
    console.log(value.price)
  }
}
  • 위의 코드처럼 따로 interface을 구별하는 함수를 만드는 방법 또한 존재한다.
  • is 라는 키워드를 통해 반환값이 Person 타입이 들어오는 검사하고 들어오지 않았다면 undefined을 반환하도록 하였다.
  • 그리고 isPerson 함수를 이용하여 타입 가드가 작동되도록 도와주었다.

 

 

export {};

interface Person {
    type: 'Person';
    name: string;
    age: number;
}
interface Product {
      type: 'Product';
    name: string;
    price: number;
}

function print(value: Person | Product) {
  if( 'age' in value){
      console.log(value.age)
  } else{
    console.log(value.price)
  }
}

위의 코드처럼 자바스크립트의 기능인 in을 이용하여 'age'라는 값이 value에 존재하는지 판별하여 Person, Product 둘 중 어떤 interface가 들어왔는지 구별해주어 타입 가드가 작동되도록 도와주었다. 

 

 

 

 

반응형

'프로그래밍 개발 > Typescript' 카테고리의 다른 글

Typescript 타입 추론  (0) 2021.05.11
Typescript 조건부 타입  (0) 2021.05.10
Typescript 맵드 타입(mapped type)  (0) 2021.05.10
Typescript 재네릭  (0) 2021.05.07
Typescript 타입 호환성  (0) 2021.05.07

댓글