TypeScript 5.5 infer 타입 개선으로 복잡한 유틸리티 타입 단순화하기
문제 상황
레거시 API 응답을 래핑하는 타입 시스템을 구축하던 중, 중첩된 Promise와 배열에서 실제 데이터 타입을 추출하는 유틸리티가 필요했다. 기존 TypeScript 5.4에서는 여러 단계의 타입 분해가 필요했다.
// 기존 방식 - 단계별 분해 필요
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type UnwrapArray<T> = T extends (infer U)[] ? U : T;
type ExtractData<T> = UnwrapArray<UnwrapPromise<T>>;
TypeScript 5.5 개선사항
5.5에서는 infer 절에서 직접 제약 조건을 지정할 수 있게 되었다. 중첩된 타입 추론을 한 번에 처리할 수 있어 코드가 간결해졌다.
// 개선된 방식
type ExtractData<T> =
T extends Promise<infer U extends any[]>
? U[number]
: T extends (infer V)[]
? V
: T;
// 실제 사용 예시
type APIResponse = Promise<User[]>;
type User = ExtractData<APIResponse>; // User 타입 직접 추출
실전 적용
API 클라이언트의 제네릭 타입에 적용했더니 타입 추론 성능도 개선됐다. 복잡한 조건부 타입이 단순화되면서 IDE의 타입 힌트 속도도 체감상 빨라진 느낌이다.
class APIClient {
async fetch<T extends Promise<any>>(endpoint: string): Promise<ExtractData<T>> {
const response = await fetch(endpoint);
return response.json();
}
}
특히 팀 내 주니어 개발자들이 유틸리티 타입을 이해하기 쉬워졌다는 피드백이 있었다. 타입 정의가 직관적이어야 협업이 수월하다는 걸 다시 한번 느꼈다.