조건부 타입은 타입의 형태를 동적으로 결정하는 강력한 기능이다. 타입을 입력으로 받아, 조건에 따라 다른 타입을 반환하는 형태로 이루어져 있다. 이는 다음과 같이 정의된다.
T extends U ? X : Y
여기서 T extends U
는 타입 체크를 수행하는 조건문이다. 만약 T
가 U
를 확장하거나 할당 가능하다면, X
타입을 반환하고, 그렇지 않다면 Y
타입을 반환한다.
예를 들어 다음과 같은 조건부 타입을 가정해보자.
type IsString<T> = T extends string ? "yes" : "no";
여기서 IsString<T>
는 입력된 타입 T
가 string
인지 검사하고, string
이라면 "yes"를 반환하고, 그렇지 않다면 "no"를 반환한다.
let a: IsString<string>; // "yes"
let b: IsString<number>; // "no"
조건부 타입과 함께 유니온 타입을 사용하면, TypeScript는 자동으로 각 유니온 멤버에 대해 조건부 타입을 분산한다.
type IsString<T> = T extends string ? "yes" : "no";
let c: IsString<string | number>; // "yes" | "no"
위의 경우 T
는 string | number
이므로, TypeScript는 string
에 대해 IsString<T>
를 평가하고 number
에 대해 IsString<T>
를 평가한다. 그 결과, IsString<string | number>
는 "yes" | "no"
라는 타입을 가진다.
조건부 타입은 타입을 추론하는 데에도 사용할 수 있다. 조건부 타입에서 extends
키워드를 사용하면, 그 다음에 오는 타입에서 추론할 수 있는 부분이 있다면 TypeScript는 그 부분을 추론한다.
Infer 키워드
*extends 키워드와 함꼐 사용되며, 타입스크립트가 런타임에서 타입을 추론하게 된다.
예
type LengthType<T>=T extends {length:infer U}? U: never;
type a= LengthType<{length:number}> //a 타입은 number가 된다.
예를 들어 다음과 같은 타입을 가정해보자.
type ExtractArrayElement<T> = T extends (infer E)[] ? E : never;
이 타입은 배열이 주어지면 그 배열의 요소 타입을 추론하고, 배열이 아닌 경우에는 never
타입을 반환한다.
let d: ExtractArrayElement<string[]>; // string
let e: ExtractArrayElement<number>; // never
여기서 infer E
는 T
가 배열인 경우 그 배열의 요소 타입을 E
라는 임시 타입 변수에 할당한다.
조건부 타입은 이처럼 타입의 형태를 동적으로 결정하는 데에 유용하다. 이를 통해 코드를 더 유연하게 작성할 수 있다.