TypeScript 4.2 Template Literal Types로 API 타입 안전성 개선
문제 상황
프로젝트에서 REST API 엔드포인트를 문자열로 관리하다 보니 오타로 인한 404 에러가 종종 발생했다. /api/user/:id 같은 동적 라우트는 타입 체크가 불가능해서 런타임에만 에러를 확인할 수 있었다.
Template Literal Types 적용
TypeScript 4.2에서 추가된 Template Literal Types를 사용해 타입 수준에서 엔드포인트를 검증하도록 변경했다.
type ApiVersion = 'v1' | 'v2';
type Resource = 'users' | 'posts' | 'comments';
type Endpoint = `/api/${ApiVersion}/${Resource}`;
// 유효한 엔드포인트만 허용
const endpoint: Endpoint = '/api/v1/users'; // OK
const invalid: Endpoint = '/api/v3/users'; // Error
동적 파라미터도 타입으로 표현할 수 있었다.
type UserId = `user-${string}`;
type PostId = `post-${number}`;
type DynamicEndpoint<T extends string> = `/api/v1/${T}/${string}`;
function fetchResource(endpoint: DynamicEndpoint<Resource>) {
return fetch(endpoint);
}
fetchResource('/api/v1/users/user-123'); // OK
fetchResource('/api/v1/invalid/123'); // Error
실제 적용 예시
API 클라이언트 함수에 적용해서 사용했다.
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiPath = `/api/${string}`;
interface ApiConfig<T = unknown> {
method: HttpMethod;
path: ApiPath;
body?: T;
}
async function apiCall<T>(config: ApiConfig): Promise<T> {
const response = await fetch(config.path, {
method: config.method,
body: config.body ? JSON.stringify(config.body) : undefined,
});
return response.json();
}
결과
엔드포인트 오타로 인한 버그가 눈에 띄게 줄었다. 자동완성도 잘 동작해서 개발 경험이 개선됐다. Template Literal Types는 단순해 보이지만 문자열 기반 API 작업에서 꽤 유용했다.