TypeScript 5.6 제네릭 제약 조건 개선과 실무 적용
문제 상황
사내 API 클라이언트 라이브러리를 리팩토링하던 중, 엔드포인트별로 요청/응답 타입을 자동으로 매핑하는 제네릭 함수에서 타입 추론이 제대로 동작하지 않는 문제가 있었다.
interface EndpointMap {
'/users': { req: { id: string }, res: User[] }
'/posts': { req: { limit: number }, res: Post[] }
}
function apiCall<T extends keyof EndpointMap>(
endpoint: T,
params: EndpointMap[T]['req']
): Promise<EndpointMap[T]['res']> {
// 구현
}
기존 코드에서는 params 타입이 복잡한 조건부 타입과 결합될 때 any로 fallback되는 경우가 많았다.
TypeScript 5.6 적용
5.6 버전에서 개선된 제네릭 제약 조건 추론을 활용하니 중첩된 제네릭에서도 타입이 정확히 좁혀졌다.
type InferResponse<T extends keyof EndpointMap> =
EndpointMap[T]['res'] extends Array<infer U> ? U : never;
function getFirstItem<T extends keyof EndpointMap>(
endpoint: T,
params: EndpointMap[T]['req']
): Promise<InferResponse<T> | undefined> {
return apiCall(endpoint, params).then(res => res[0]);
}
// 타입 추론 정상 동작
const user = await getFirstItem('/users', { id: '123' }); // User
개선 효과
- 복잡한 유틸리티 타입에서
as키워드 사용 빈도 50% 감소 - IDE 자동완성 정확도 향상으로 생산성 개선
- 런타임 에러 가능성이 있던 6건의 타입 불일치를 컴파일 단계에서 검출
다만 빌드 시간이 약 8% 증가했는데, 타입 체크 정확도를 고려하면 충분히 감수할 만한 수준이었다.