it공부 (개념)/javascript

union type(유니온 타입)과 type guard(타입가드)란? 개념 및 Typescript예제

cantor 2023. 1. 24. 18:26

Union?

    • 사전적 의미: 조합, 결합, 연합

 

    • in Mathematics(수학에서): 합집합

 

  • 타입스크립트에서:
      
    잠재적인 타입들을 열거해 놓은 타입이다.
    아직 어떤타입의 값이 대입될지 정해져 있지 않았을 때 사용한다.
    열거에는 | 기호를 사용한다.

    ex) number | string



자바스크립트에는 존재하지 않는 타입스크립트 고유의 문법요소이다.

 

 

 

Union Type 예제

//TypeScript 코드

//string과 number중 하나를 가질 수 있는 타입

type stringOrNumber = string | number;


//string 

let burgerName: stringOrNumber;
burgerName = 'HamBurger';

// number

let price: stringOrNumber;
price = 3000;




//자바스크립트는 유니온 타입을 갖고있지 않다.
//컴파일후 관련 코드는 사라진다.

// 컴파일된 자바스크립트 코드

let burgerName;
burgerName = 'HamBurger';
let price;
price = 3000;

 

 

 

Union type을 사용할 시 발생하는 오류

 

유니온 타입을 사용하여 코드를 작성하면

타입스크립트 컴파일러는  "타입체크"를 수행할 수 없다.

//JS코드

function add(a, b) {
    return a + b;
}

// 실행결과가 예상과 다를 순 있어도, 컴파일도중에 오류가 발생하진 않는다.


//TS코드

function add(a: number | string, b: number | string): number | string {
        return a + b;
}

//코드 작성중 TS 컴파일러가 오류를 체크해준다

 

타입스크립트가 알려주는 오류.

 

 

이렇게 "타입체크"문제를 해결하기 위해 

유니온 타입으로 표현된 요소가 가지고있는 타입을 검사하는 코드를 따로 삽입해야 한다.

 

이러한 검사 코드를 Type Guard라고 한다.

 

 

Type Guard(타입 가드)?

    • Guard의 사전적 의미:

      동사: 특정 대상을 보호하거나 조종하기 위해 살피다.
      명사: 보호물, 억제 통제수단
  • 타입스크립트의 타입 가드:

    union type에 대입되는 타입을 검사하여 
    타입체크기능을 수행하는 코드

 

 

Type Guard 구현하기

 

1.'typeof' 연산자 

 

 

유니온타입이 string, number 등의 기본 타입들로만 구성되어 있을 경우에 사용한다.

 

 

if 문과 typeof 연산자를 결합하여 타입가드를 구현할 수 있다.

function add(a: number | string, b: number | string): number | string {
   
   //타입가드: a와 b 가 number일 경우
   
   if (typeof a === 'number' && typeof b === 'number') {
        return a + b}
   
   //타입가드 a와 b가 string일 경우
   
   else if (typeof a === 'string' && typeof b === 'string') {
        return a + b 
    }

    else {return 'a and b should have same type'}
}


//위의 코드의 두개의 if문이 type guard 역할을 수행한다.

 

 

2. 타입가드를 요구하지 않는 예시

타입가드가 필요없는 예시
type CheeseBurger = {
    numBread: number;
    numCheese: number;
}

type BeefBurger = {
    numBread: number;
    numBeef: number;
}

// 재료를 알려주는 함수
// parameter가 union type으로 되어있다.

function sayIngredient (burger: CheeseBurger | BeefBurger) {
    console.log('number of bread : ' + burger.numBread)
    }
    


 //numBread는 CheeseBurger와 BeefBurger 전부 가지고있는 요소이다.
 // 그래서 TS 컴파일러가 이미 알고있기때문에
 // Type Guard가 필요없다.

 

 

 

 

3.  "typeof"는 내가 정의한 커스텀타입에는 사용할 수없다.

// burger매개변수는 유니온타입이 지정되어있다.

function sayIngredient (burger: CheeseBurger | BeefBurger) {

//BeefBurger일때만 실행되는 코드. 그러니
// 커스텀타입은 typeof로 체크해줄수 없다.

if (typeof burger === 'BeefBurger') {
        console.log('number of beef : ' + burger.numBeef
    }

console.log('number of bread : ' + burger.numBread)
    }

위와 같은 코드 입력하면 다음과 같은 오류메시지를 읽을 수 있다.

 

typeof를 사용해서 커스텀 타입을 체크할 수는 없다.

 

typeof의 반환값은

"string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"

 

등등의 기본 내장 타입으로 구성된다.

 

따라서 typeof buger의 반환값이 "BeefBurger"가 되는 것은 불가능하다.

 

*아마도 typeof buger의 반환값은 object일 것이다.

 

3. 커스텀 타입 타입가드: 성분을 추적하는 "in"을 활용하기.

function sayIngredient (burger: CheeseBurger | BeefBurger) {
    console.log('number of bread : ' + burger.numBread)
    
    //타입가드 numCheese와 numBeef요소의 존재로
    // CheeseBurger인지 BeefBurger인지 검사한다.
    
    if('numCheese' in burger) {
        console.log('number of cheese : ' +  burger.numCheese)
    } else if ('numBeef' in burger) {
        console.log('number of beef : ' + burger.numBeef)
        }
    
}

 

 

3. 클래스 유니온타입: instanceof를 활용하자.

 

인스턴스가 대입되는 자리의 매개변수를 클래스 유니온타입으로 구성한 경우엔

instanceof와 if문을 결합한 타입가드를 사용한다.

class Burger {
    public setMenu = 'french fries and coke'

}

class SideMenu {
    public beverage = 'coke or cider'
}

const order1 = new Burger()
const order2 = new SideMenu()

//burger와 sideMenu의 유니온타입을 
//매개변수의 타입으로 지정한 함수

function checkPlusOrder (order: Burger | SideMenu) {
    if (order instanceof Vurger){
        console.log(order.setMenu);
    }
    if (order instanceof SideMenu){
        console.log(order.beverage);
    }
}
//instanceof를 이용하여 order가 어떤 class에 속하는지 체크한다.

 

 

4. discriminated union을 사용하자.

 

discriminated란 구별되는, 차별되는 이라는 뜻이다.

 

유니온타입에 들어가는 "구분대상"의 개별요소에

구분을 위한 성분을 집어넣고, switch문을 타입가드로 이용한다.


// interface에 kind라는 구분용 요소를 넣어놓았다.

interface Burger {
    kind: "burger";
    setMenu: string;
}

interface SideMenu {
    kind: "sideMenu";
    beverage: string;
}


function checkPlusOrder(order: Burger | SideMenu) {
    switch (order.kind) {
        case "burger":
            console.log(order.setMenu);
            break;
        case "sideMenu":
            console.log(order.beverage);
            break;
    }
}
//switch문과 기존의 interface에 심어놓은 구분용변수  "kind"
//를 이용하여 type guard를 구현하였다.

 

 

 

 

 

더 읽을거리

 

https://batcave.tistory.com/37

 

Intersection type(인터섹션 타입) 개념 및 Typescript 예제

Intersection? 사전적 의미: 교차로, 교집합, 어떤 것들이 가로지르는 지점 Intersection type (in Typescript): 여러 타입을 융합하여 만든 하나의 타입. "&" 연산자를 활용하여 정의한다. 융합된 타입들의 요

batcave.tistory.com

https://batcave.tistory.com/33

 

TypeScript(타입스크립트)? 간단하게 알아보기

Typescript icons created by Freepik - Flaticon TypeScript(타입스크립트 이하 TS)란? 프로그래밍언어: JavaScript(자바스크립트, 이하 JS)의 super set(상위집합) JS에 새로운 요소를 추가하여 만든 언어. Type check(타입

batcave.tistory.com

 

https://batcave.tistory.com/34

 

VSCODE에서 TypeScript 개발 준비하기

썸네일 이미지 Microsoft icons created by Freepik - Flaticon 저번에 소개했던 TypeScript의 개발준비를 위한 설정을 해보자. https://batcave.tistory.com/33 TypeScript(타입스크립트)? 간단하게 알아보기 Typescript icons cre

batcave.tistory.com

 

이미지 출처

Guard icons created by max.icons - Flaticon Team icons created by Freepik - Flaticon

 

참고 타입스크립트 deep-dive document

https://radlohead.gitbook.io/typescript-deep-dive/

 

읽어주셔서 감사합니다.

오탈자나 미흡한 부분은 지적해 주세요.

 

혹은 더 알려주고 싶은 부분도 말씀해 주시면 감사하겠습니다.

 

다들 항상 행복하세요