TypeScript 4.6 조건부 타입 추론 개선으로 타입 가드 리팩토링
문제 상황
프로젝트를 TypeScript 4.6으로 업그레이드하면서 기존에 작성했던 타입 가드 함수들을 점검하게 되었다. API 응답을 처리하는 유틸리티 함수에서 타입 추론이 제대로 작동하지 않아 불필요한 타입 단언을 여러 곳에서 사용하고 있었다.
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string };
function processResponse<T>(response: ApiResponse<T>) {
if (response.success) {
// 4.5에서는 여기서 data 타입이 제대로 추론되지 않음
return (response as Extract<ApiResponse<T>, { success: true }>).data;
}
throw new Error(response.error);
}
4.6의 개선사항
TypeScript 4.6에서는 조건부 타입에서 dependent parameter의 타입 추론이 크게 개선되었다. 이제 discriminated union을 사용할 때 타입 narrowing이 훨씬 정확하게 작동한다.
function processResponse<T>(response: ApiResponse<T>): T {
if (response.success) {
return response.data; // 타입 단언 없이 작동
}
throw new Error(response.error);
}
// 제네릭 타입 가드도 개선됨
function isSuccessResponse<T>(
response: ApiResponse<T>
): response is Extract<ApiResponse<T>, { success: true }> {
return response.success;
}
적용 결과
프로젝트 전체에서 약 30여 곳의 타입 단언(as)을 제거할 수 있었다. 특히 API 레이어와 상태 관리 로직에서 코드가 간결해지고 타입 안정성도 높아졌다. 컴파일 타임에 잡히는 에러도 몇 건 발견했는데, 기존에 타입 단언으로 우회했던 부분에서 실제 로직 오류가 숨어있었던 것으로 확인되었다.
참고사항
다만 --strictNullChecks 옵션을 켜지 않은 레거시 코드베이스에서는 여전히 일부 추론이 제대로 작동하지 않았다. 점진적으로 strict 모드를 적용하는 것이 필요해 보인다.