[TypeScript] Union Type

Joah·2022년 10월 5일
0

TypeScript

목록 보기
12/16

🏕 String Literal Types

지정한 문자열 그대로만 타입으로 할당할 수 있다.

예를 들어,

type Name = "Joah"

let myName : Name = "Joah"
let hisName : Name = "Steve"  //error
let herName : Name = "Meg"    //error

//타입 Name에는 문자열 Joah만 쓸 수 있다. 다른 문자열은 사용될 수 없다.

type Age = 23

let myAge : Age = 23
let hisAge : Age = 11    //error
let herAge : Age = 43    //error

굳이 이걸 왜 쓰는거지....?
아래의 Union type과 관련이 있다.



🏕 Union Type

타입스크립트에서 굉장히 많이 쓰이는 타입 중 하나이다.

OR로 이해하면 된다.

발생할 수 있는 모든 케이스 중에서 하나만 정하고 싶을 때 주로 사용된다.


type Direction = "left" | "right" | "up" | "down";
//direction이라는 타입은 총 4가지의 값을 가질 수 있다.

function move(direction : Direction){
  console.log(direction)
}

move('left')



type Tile = 8 | 16 | 32;
const bathTile : Tile = 33;  //error
const yardTitle : Tile = 16;
  • move라는 함수에 인자로 direction을 넣을 것인데 그 direction에 들어올 수 있는 문자열은 좌|우|위|아래 4가지 뿐이다.

  • 따라서 move 함수를 호출할 때 인자로 Direction type에서 정의한 타입만 넣을 수 있다.

  • 꼭 문자열이 아니더라도 다양한 타입을 지정할 수 있다.


하나의 alias type안에 여러가지 타입을 지정할 수 있다.

//Union Type

type Direction = "left" | 4234 | [1,2,3] | true;
//direction이라는 타입은 총 4가지의 값을 가질 수 있다.

function move(direction : Direction){
  console.log(direction)
}

move([1,2,3]);
move("left");

가능가능!


🙏🏼 실전 예제

  • 로그인을 했을 때 로그인 성공과 로그인 실패에 대한 응답을 타입 스크립트로 작성
type Success = {
    response : {
      body: String;
    }
  }

  type Fail = {
    reason : String; 
  }

  type LoginStatus = Success | Fail

  function login(): LoginStatus{
    return {
      response : {
        body : "good
      };
    }
  }

//만약 fail이라면
function login(): LoginStatus{
	return {
    	reason : "bad request"
    };
}
  • 로그인에 성공했을 때 응답을 body안에 String형식으로 작성할 수 있도록 한다.

  • 로그인에 실패했을 때는 그 이유를 String형식으로 작성할 수 있도록 한다.

function login():Success | Fail{}

이렇게 작성해도 되지만 가독성 있게 코드를 다시 작성하면

type LoginStatus = Success | Fail

따로 타입을 지정해서 사용할 수 있다.

  • 만약 로그인 성공이라면 return을 Success에 맞게 작성해야 한다.

보통 비동기로 네트워크 통신을 하니깐 return 되는 것은 Promise이다.
따라서 원래는 Promise<LoginStatus> 이다.


이제 로그인의 상태에 대해 출력하는 함수를 작성해보자

type Success = {
    response : {
      body: String;
    }
  }

type Fail = {
  reason : String; 
}

type LoginStatus = Success | Fail


function printLoginStatus(status: LoginStatus): void{
  if('response' in status) {
    console.log(`🌈 ${status.response.body}`)
  }else {
    console.log(`💩 ${status.reason}`)
  }
}
  • 사실 printLoginStatus 함수는 아무것도 return 하지 않기 때문에 void를 작성했지만 생략가능하다.

  • if 문에서 "만약 status안에 response가 있다면"으로 시작하면 Success가 인자로 들어간거고

  • 그렇지 않다면 Fail이 인자로 들어간 것이다.


이렇게 "response"를 작성하려고 해도 TypeScript는 알아서 Fail에는 reason이 있으니 reason을 추천한다.

하지만 response in status를 사용하는 것 보다 더 권장되는 방법이 있다.



🏕 Discriminated Union

동일한 key 이름과 다른 value

즉, 동일한 result라는 키 이름에 status 별로 가지고 있는 다른 value를 부여한다.

따라서 공통적인 프로퍼트를 가지고 있어 직관적으로 코드를 작성할 수 있고 가독성도 향상된다.


//우선 성공, 실패 모두 동일한 key인 result를 부여한다.
// value에는 각 상태에 따른 다른 값을 넣는다.

  type Success = {
    result: "success!!!";
    response: {
      body: String;
    };
  };

  type Fail = {
    result: "Fail!!!";
    reason: String;
  };

  type LoginStatus = Success | Fail;


//만약 status의 동일한 key인 result의 값이 "success!!!" 라면...

  function printLoginState(status: LoginStatus): void {
    if(status.result === "success!!!"){
      console.log(`🌈 ${status.response.body}`)
    }else {
      console.log(`💩 ${status.reason}`)
    }
  }


역시 타입스크립트는 아주 똑똑하게 status.result에 어떤 값이 있는지 미리 추천한다.

아래 콘솔 출력 명령문도 타입스크립트가 추천을 해준다. 그대로 작성하면 된다.

profile
Front-end Developer

0개의 댓글