Post

타입스크립트 - 컨디셔널 타입

컨디셔널 타입

조건에 따라 다른 타입이 되는 타입

1
2
3
특정 타입 extends 다른 타입
  ? 참일  타입
  : 거짓일  타입
1
2
3
4
5
type A1 = string;
type B1 = A1 extends string ? number : boolean; // type B1 = number

type A2 = number;
type B2 = A2 extends string ? number : boolean; // type B2 = boolean
  • A1이 string이기때문에 B1은 조건문이 참이다. 따라 B1은 number 타입이 된다.
  • A2이 number이기때문에 B2은 조건문이 거짓이다. 따라 B2는 boolean 타입이 된다.

컨디셔널 타입은 타입 검사를 위해서도 많이 사용한다.

1
2
type Result = "hi" extends string ? true : false; // type Result = true
type Result2 = [1] extends [string] ? true : false; // type Result2 = false
  • Result의 ‘hi’의 타입을 검사, ‘hi’는 string이기 때문에 조건문이 참이다. 따라 Result는 true가 된다.
  • Result2의 [1]의 타입을 검사, [ 1 ]는 [number]이기때문에 조건문이 거짓이다. 따라 Result2는 false가 된다.

타입이 맞으면 배열로 만들고, 아닐 경우에는 nerver로 만들 때 사용 (예외처리)

제네릭과 함께 사용

1
2
3
type ChooseArray<A> = A extends string ? string[] : never;
type StringArr2 = ChooseArray<string>; // type StringArr2 = string
type NumberArr2 = ChooseArray<number>; // type NumberArr2 = never
  • 타입 ChooseArray는 <A>가 string이면 string[]로 만들고 아닐 경우 never가 된다.

중첩해서 사용 가능

1
2
3
4
5
6
7
8
9
10
11
12
type ChooseArray2<A> = A extends string
  ? string[]
  : A extends boolean
  ? boolean[]
  : never;

type StringArr3 = ChooseArray2<string>;
// type StringArr3 = string[]
type BooleanArr3 = ChooseArray2<boolean>;
// type BooleanArr3 = boolean[]
type NumberArr3 = ChooseArray2<number>;
// type NumberArr3 = never
1
2
3
type Start = string | number;
type Result = Start extends string ? Start[] : never;
// type Result = never
  • type Result = string | number extends string
  • stringnumber이 string을 extends할 수 없기때문에 never가 됨

컨디셔널 타입을 제네릭과 함께 사용하면 Start[]타입으로 지정할 수 있음

1
2
3
4
5
type Start = string | number;
type Result<Key> = Key extends string ? Key[] : never;
// Key in type Result<Key>
// let n: string[]
let n: Result<Start> = ["hi"];
1
2
3
Result<Start>
=> type Result<string | number> = Result<string> | Result<number> extends string
=> string[]

boolean 분배법칙 막기

1
2
3
4
5
6
7
8
9
type Start = string | number | boolean;
type Result<Key> = Key extends string | boolean ? Key[] : never;
// Key in type Result<Key>

let n: Result<Start> = ["hi"];
// let n: string[]

n = [true];
// let n: string[] | false[] | true[]
string[]boolean[]을 원했지만 [true]일 때는 string[] | false[] | true[]로 boolean이 분배 법칙이 일어나 boolean을 falsetrue로 인식했기 때문
1
2
3
type IsString<T> = T extends string ? true : false;
type Result = IsString<"hi" | 3>;
// type Result = boolean
  • type Result = IsString<'hi'>type Result = IsString<3>;
  • truefalse 가 되기때문에
  • 최종적으로 boolean 타입이 됨

분배 법칙을 막으려면?

배열로 제네릭을 감싸면 분배법칙이 일어나지 않는다.

1
2
3
type IsString<T> = [T] extends [string] ? true : false;
type Result = IsString<"hi" | 3>;
// type Result = false
  • type Result = IsString<'hi' | 3> extends string을 확인
  • 최종적으로 false 타입이 됨
This post is licensed under CC BY 4.0 by the author.