TypeScript 5.2 satisfies 연산자로 타입 안전성 높이기
문제 상황
프로젝트에서 설정 객체를 다루다가 타입 오류가 자주 발생했다. as const를 쓰면 너무 좁아지고, 인터페이스로만 타이핑하면 오타를 잡지 못했다.
const config = {
development: { apiUrl: 'http://localhost:3000' },
production: { apiUrl: 'https://api.example.com' },
staging: { apiUrl: 'https://staging.api.example.com' }
};
// apiUrl 오타를 내도 에러가 안 남
config.development.apiUr;
satisfies 연산자 도입
TypeScript 5.0부터 지원되는 satisfies를 사용하면 타입 체크는 하면서도 추론을 유지할 수 있다.
type Environment = 'development' | 'production' | 'staging';
type Config = Record<Environment, { apiUrl: string }>;
const config = {
development: { apiUrl: 'http://localhost:3000' },
production: { apiUrl: 'https://api.example.com' },
staging: { apiUrl: 'https://staging.api.example.com' }
} satisfies Config;
// 이제 오타를 잡아준다
config.development.apiUrl; // OK
// config.development.apiUr; // Error
실전 활용 케이스
라우트 설정에도 적용했다. 기존에는 as const로 처리했는데, satisfies를 쓰니 타입 안전성과 자동완성이 모두 개선됐다.
type Route = {
path: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
};
const routes = {
getUser: { path: '/users/:id', method: 'GET' },
createUser: { path: '/users', method: 'POST' }
} satisfies Record<string, Route>;
// 타입 추론이 정확하게 된다
routes.getUser.method; // 'GET' (literal type)
마이그레이션 시 주의점
팀 전체가 TypeScript 5.0 이상을 사용해야 한다. CI/CD 파이프라인의 Node 버전도 확인이 필요했다. 우리는 Node 18 LTS를 쓰고 있어서 문제없었다.
as 단언을 무작정 satisfies로 바꾸면 안 된다. as는 강제 변환이고 satisfies는 검증이므로 용도가 다르다. 기존 코드에서 as를 남발했다면 satisfies로 바꿀 때 타입 에러가 많이 날 것이다. 그게 정상이다.