TypeScript 4.2 Template Literal Types로 타입 안전성 높이기

문제 상황

프로젝트에서 REST API 엔드포인트를 문자열로 관리하다 보니 오타로 인한 런타임 에러가 종종 발생했다. 특히 동적 경로 파라미터가 포함된 경우 타입 체크가 불가능했다.

// 기존 방식
const endpoint = `/api/users/${userId}/posts/${postId}`;
// 오타가 나도 컴파일 타임에 잡을 수 없음

Template Literal Types 적용

TypeScript 4.2에서 추가된 Template Literal Types를 사용해 타입 수준에서 문자열 패턴을 정의했다.

type ApiPath = `/api/users/${string}/posts/${string}` | `/api/users/${string}`;

function fetchApi(path: ApiPath) {
  return fetch(path);
}

// 타입 체크 통과
fetchApi(`/api/users/123/posts/456`);

// 컴파일 에러 발생
fetchApi(`/api/user/123`); // 'user' 오타

더 나아가 유틸리티 타입과 결합해 동적으로 타입을 생성했다.

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiRoute = `${HttpMethod} /api/${string}`;

const routes: Record<string, ApiRoute> = {
  getUser: 'GET /api/users',
  createPost: 'POST /api/posts',
};

결과

타입 안전성이 크게 향상되었고, IDE 자동완성 지원도 개선되었다. 다만 너무 복잡한 패턴은 타입 추론 성능에 영향을 줄 수 있어 적절한 수준에서 사용하는 것이 중요했다.

리팩토링 과정에서 기존에 숨어있던 잠재적 버그 3건을 발견했다. 점진적으로 전체 API 레이어에 적용할 계획이다.

TypeScript 4.2 Template Literal Types로 타입 안전성 높이기