TypeScript 3.4에서 const assertion 활용하기

문제 상황

API 응답 상태 코드를 처리하는 코드를 작성하던 중, 타입이 너무 넓게 추론되는 문제가 있었다.

const STATUS_CODES = {
  OK: 200,
  CREATED: 201,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401
};
// typeof STATUS_CODES.OK => number

리터럴 타입을 유지하려면 각각 타입을 명시하거나 enum을 사용해야 했는데, 코드가 장황해졌다.

const assertion 적용

TypeScript 3.4에서 추가된 as const를 사용하면 간단히 해결된다.

const STATUS_CODES = {
  OK: 200,
  CREATED: 201,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401
} as const;
// typeof STATUS_CODES.OK => 200

type StatusCode = typeof STATUS_CODES[keyof typeof STATUS_CODES];
// StatusCode => 200 | 201 | 400 | 401

객체뿐만 아니라 배열에도 적용할 수 있다.

const ROUTES = ['/home', '/about', '/contact'] as const;
type Route = typeof ROUTES[number];
// Route => '/home' | '/about' | '/contact'

실무 적용

API 클라이언트 코드에서 유용하게 사용했다. 특히 Redux action type이나 라우트 경로처럼 정확한 문자열/숫자 타입이 필요한 곳에서 효과적이었다.

const ACTION_TYPES = {
  FETCH_USER: 'user/fetch',
  UPDATE_USER: 'user/update'
} as const;

type ActionType = typeof ACTION_TYPES[keyof typeof ACTION_TYPES];

function dispatch(type: ActionType) {
  // type은 정확한 리터럴 타입으로 추론됨
}

enum보다 가볍고 JavaScript 출력도 깔끔해서 앞으로 자주 사용할 것 같다.

TypeScript 3.4에서 const assertion 활용하기