Conditional Types

TypeScript에서 삼항 연산자를 이용해 타입을 지정하는 방식입니다.

 

예시) TypeScript에 내장된 Utility Types의 Extract 타입

type Extract<T, U> = T extends U ? T : never

T extends U 가 참이면 T를, 그렇지 않으면 never를 반환합니다.

 

삼항 연산자의 조건문에 올 수 있는 문법에는 extends 키워드 밖에 없습니다.

extends

extends 키워드는 슈퍼 클래스를 서브 클래스에게 상속해 줄 때 사용하는 키워드입니다.

타입 지정 시, extends 키워드는 T extends U 에 대해 T 는 U 에 포함된다는 의미입니다.

 

extends 키워드가 사용되는 조건문 예시를 살펴보며 제대로 이해한 게 맞는지 확인해보겠습니다.

다음 조건문들은 true 로 평가될까요? 아니면 false 로 평가될까요? 

1. 10000 extends number : 10000은 number에 포함되므로 true입니다.

2. number extends 10000 : number는 TypeScript에 존재하는 모든 숫자를 나타내는 타입이고, 숫자 10000은 1000일 뿐입니다. number 가 10000보다 더 큰 개념이므로 false입니다.

3. string[ ] extends any : any는 TypeScript에 존재할 수 있는 모든 타입의 교집합이므로 전체 집합이라고 생각해도 무방합니다. 그러므로 string[]은 any에 포함되므로 true입니다.

4. never extends any : never를 공집합으로 생각한다면 never는 any에 포함되므로 true입니다.

infer

infer 키워드는 삼항 연산자의 조건문에 쓰이는 타입 중 하나를 이름 붙여서 빼 와서 삼항 연산자의 true 절이나 false 절에 사용합니다.

infer 키워드가 사용되는 예시) 함수 타입을 인자로 받아서 해당 함수의 반환값의 타입을 Promise로 감싸 반환하는 PromiseReturnType

type AnyFunction = (...args: any) => any;
type PromiseReturnType<F extends AnyFunction> = F extends (...args: any) => infer R ? Promise<R> : never

PromiseReturnType은 하나의 타입을 인자 F로 받아서, 어떠한 조건문을 거쳐 Promise<R>이나 never를 반환합니다.

타입을 인자로 받는 부분을 먼저 살펴보겠습니다.

F extends (...args: any) => any

인자로 받을 타입 F는 F extends (...args: any) => any 조건을 만족해야 합니다. 즉 F는 반드시 함수여야 합니다.

 

우변항을 살펴보겠습니다.

F extends (...args: any) => infer R ? Promise<R> : never

F extends (...args: any) => infer R 이 참이면 Promise<R>을, 그렇지 않으면 never를 반환합니다.

 

복사했습니다!