문제
제네릭 타입 안에 숨어있는 타입을 꺼내고 싶을 때가 있다. Promise 안의 반환 타입이라든가, 배열 요소의 타입이라든가. 매번 타입을 수동으로 지정하자니 귀찮고, 변경될 때마다 같이 바꿔줘야 하는 게 짜증났다.
해결
infer 키워드를 쓰면 conditional type 안에서 타입을 추론해서 변수처럼 꺼낼 수 있다.
// Promise 안의 타입 추출
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Result = UnwrapPromise<Promise<string>>; // string
type Plain = UnwrapPromise<number>; // number
실무에서 자주 쓰는 패턴 몇 가지 더 보면:
// 함수 반환 타입 추출
type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never;
const fetchUser = async () => ({ id: 1, name: 'Kevin' });
type User = ReturnOf<typeof fetchUser>; // Promise<{ id: number; name: string }>
// 배열 요소 타입 추출
type ElementOf<T> = T extends (infer E)[] ? E : never;
type Item = ElementOf<string[]>; // string
API 응답 타입을 다룰 때 진짜 유용하다:
type ApiResponse<T> = {
data: T;
status: number;
};
// data 필드의 타입만 꺼내기
type ExtractData<T> = T extends ApiResponse<infer D> ? D : never;
type UserData = ExtractData<ApiResponse<{ id: number; name: string }>>;
// { id: number; name: string }
핵심 포인트
infer는extends조건부 타입 안에서만 쓸 수 있다- TypeScript 내장 유틸리티
ReturnType,Parameters등이 전부infer로 만들어진 거다 - 중첩된 제네릭에서 타입을 꺼낼 때 수동 지정 대신
infer를 쓰면 타입 안전성이 자동으로 따라온다
댓글