Typescript

Conditional types

bkdragon 2023. 3. 22. 17:28

타입을 정의할 때 입력에 따라서 다르게 정의할 수 있을까? 당연히 가능하다. 대부분의 프로그래밍 언어처럼 타입스크립트에서도 if문의 역할을 하는 기능이 있다. 바로 Conditional types이다.

T extends U ? X : Y

T타입이 적어도 U타입이라면 X타입 아니라면 Y타입이 된다.

 

이 개념을 사용한 타입챌린지 문제를 보자. 

https://github.com/type-challenges/type-challenges/blob/main/questions/00268-easy-if/README.ko.md

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

 

if 타입을 구현하는 문제인데, C타입 참일 때 T, 거짓을 때 F를 반환해야한다. Conditional types을 이용하면 다음과 같이 작성할 수 있다.

type If<C, T, F> = C extends true ? T : F;

그런데 여기까지만 하면 예외처리가 안된다. C로 어떠한 타입도 대입이 될 수 있다. 

 

constraint(제약조건)을 줄 수 있다.

type If<C extends boolean, T, F> = C extends true ? T : F;

이렇게 되면 C 타입에는 적어도 boolean 타입만 대입될 수 있다.

 

Conditional types를 이용하여 타입 추론도 가능하다. infer 키워드를 이용한다. 타입을 정의하는 시점에서 알 수 없는 타입을 가상의 타입으로 정하고 사용한다.

https://github.com/type-challenges/type-challenges/blob/main/questions/00002-medium-return-type/README.ko.md

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

리턴 타입을 반환해야하는 문제이다. 타입을 정의하는 시점에서는 무슨 타입이 반환될지 모르니 infer를 사용할 수 있다.

type MyReturnType<T extends (...arg : any[]) => any > = T extends (...arg : any[]) => infer R ? R : never;

 

추가적으로 알아둬야할 유용한 개념이 있다. Distributive Conditinal types, Conditinal types이 유니온 타입을 만나면 분산적으로 동작한다는 개념이다.

https://github.com/type-challenges/type-challenges/blob/main/questions/00043-easy-exclude/README.ko.md

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

Exclude 타입을 구현하는 문제이다.

type MyExclude<T, U> = T extends U ? never : T;

정답은 다음과 같다. T가 유니온 타입이라면 하나씩 U와 비교하고 결과 역시 유니온 타입으로 나올 것이다.

그런데 T가 유니온 타입이라고 제약조건을 걸 필요가 있을까? 전혀 없다. 아니면 아닌거니까!

 

마지막으로 문제를 하나만 더 살펴보려고 한다.

https://github.com/type-challenges/type-challenges/blob/main/questions/00062-medium-type-lookup/README.ko.md

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

Lookup 타입을 구현하는 문제이다. 유니온 타입의 특정 속성을 기준으로 조회한다. U가 유니온 타입인걸 알았으니 약간 꼼수로 extends에 왼쪽에 오겠구나 하고 생각할 수도 있다.

type LookUp<U, T> = U extends {type : T} ? U : never;

 

여러가지 문제를 통해 Conditinal types를 알아보았다.