TypeScript 4.9의 satisfies 연산자로 타입 안정성 개선하기
문제 상황
프로젝트에서 설정 객체를 다루다가 타입 안정성 문제에 부딪혔다. as const를 쓰면 리터럴 타입은 보존되지만 구조 검증이 안 되고, 타입 단언을 쓰면 추론이 넓어져서 자동완성이 제대로 안 됐다.
type Colors = {
[key: string]: string | { r: number; g: number; b: number }
};
const palette = {
primary: '#0066cc',
secondary: { r: 255, g: 0, b: 0 },
danger: '#ff0000'
} as Colors;
// 타입이 string | { r: number; ... }로 넓어져서 자동완성 불가
palette.primary.toUpperCase(); // 에러
satisfies 연산자
TypeScript 4.9에서 11월에 추가된 satisfies 연산자가 이 문제를 해결해줬다.
const palette = {
primary: '#0066cc',
secondary: { r: 255, g: 0, b: 0 },
danger: '#ff0000'
} satisfies Colors;
// 리터럴 타입이 유지되면서 Colors 타입도 검증됨
palette.primary.toUpperCase(); // 정상 작동
palette.secondary.r; // 정상 작동
타입을 만족하는지 검증하면서도 실제 값의 타입 추론은 그대로 유지된다. API 응답 스키마 검증이나 라우트 설정 같은 곳에서 특히 유용했다.
적용 사례
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'으로 좁혀진 타입
as const satisfies 조합도 가능해서 완전한 불변성과 타입 검증을 동시에 얻을 수 있었다. 팀원들과 공유했더니 설정 파일 작성할 때 바로 적용하더라.