infer

infer 키워드가 선언된 위치의 타입을 추론하여 변수에 저장합니다.

함수 반환 타입 추출

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

type T1 = ReturnType<() => string>; //string
type T2 = ReturnType<(x: string) => boolean>; //boolean
type T3 = ReturnType<string>; //never (함수가 아니므로)

함수 매개변수 타입 추출

type Parameters<T> = T extends (...args: infer P) => any ? P : never;

type P1 = Parameters<(a: string, b: number) => void>; //[string, number]
type P2 = Parameters<() => void>; //[]

배열과 튜플의 요소 타입 추출

type First<T> = T extends [infer F, ...any[]] ? F : never;

type F1 = First<[string, number, boolean]>;  //string
type F2 = First<[]>; //never
type F3 = First<[50]>; //50

type Last<T> = T extends [...any[], infer L] ? L : never;

type L1 = Last<[string, number, boolean]> //boolean
type L2 = Last<[42, "hello"]> //"hello"

Promise 값 타입 추출 (Awaited 구현)

type Awaited<T> = T extends Promise<infer U> ? U : T;
// Promise 타입이면 U 위치의 제네릭 타입을 추론하여 U 타입을 할당, 아니라면 T 타입을 할당

type A1 = Awaited<Promise<string>>; //string
type A2 = Awaited<string>; //string
type DeepAwaited<T> = T extends Promise<infer U> ? DeepAwaited<U> : T;
//재귀적으로 처리

type D1 = DeepAwaited<Promise<Promise<string>>>; //string
type D2 = DeepAwaited<Promise<Promise<Promise<number>>>>; //number

객체에서 특정 속성 타입 추출

type GetProperty<T, K extends keyof T> =
	T extends { [P in K]: infer V } ? V : never;

type PropType1 = GetProperty<{ name: string; age: number }, 'name'>;
type PropType2 = GetProperty<{ name: string; age: number }, 'age'>;