-
TypeScript Enums vs as constLanguages/TypeScript 2024. 4. 21. 14:40
TypeScript를 사용하면서 상수를 지정할 때 enum과 as const의 방식이 있습니다. 팀 단위로 개발을 진행하면서 상수 지정에 대한 컨벤션은 따로 없었고 팀원들의 스타일에 따라 각각 사용 중이었습니다. 상수 지정 방식을 통일하고 해당 내용을 정리할 겸 enum과 as const의 차이를 알아보겠습니다.
Enums
enum
예시로 enum을 사용하여 상수를 지정합니다.
// 숫자 열거형 enum Direction { // 따로 할당된 값이 없을 경우 0부터 차례로 할당 됨. Up, Down, Left, Right, } // 문자열 열거형 enum DirectionString { Up = 'UP', Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT', }
숫자 열거형 enum을 사용 시에 가독성은 좋아 보이지만 해당 코드를 transpile 할 경우 아래와 같이 나오게 됩니다.
enum Direction { Up, Down, Left, Right, } let up = Enum.Up; let nameOfUp = Enum[up]; // "Up" // transpile var Direction; (function (DIRECTION) { DIRECTION[DIRECTION["Up"] = 0] = "UP"; DIRECTION[DIRECTION["Down"] = 1] = "DOWN"; DIRECTION[DIRECTION["Left"] = 2] = "LEFT"; DIRECTION[DIRECTION["Right"] = 3] = "RIGHT"; })(DIRECTION || (DIRECTION = {})); let up = Enum.Up; let nameOfUp = Enum[up]; // "Up"
위의 코드에서 숫자 열거형 enum은 값에서 필드로 맵핑할 수 있는데 이를 Reverse mappings라고 부릅니다. 아래와 같은 형태로 transpile이 되는 것입니다.
enum Direction { Up, Down, Left, Right, } // transpile var Direction = { Up: 0, Down: 1, Left: 2, Right: 3, '0': 'Up', '1': 'Down', '2': 'Left', '3': 'Right', }
enum을 transpile 시 필드에 값을 할당하는 함수가 IIFE 형태로 선언되어 있습니다. Tree Shaking에 최적화된 Rollup의 경우 enum을 사용하지 않더라도 transpile 시 IIFE 형태로 선언되어 있어 Tree Shaking이 되지 않는 이슈가 있습니다.
참고로 문자열 열거형에서는 Reverse mappings가 발생하지 않습니다.
const enum
Reverse mappings을 막고 좀 더 엄격하게 관리를 위해 const enum을 사용합니다. 예시로 확인해 보겠습니다.
const enum Direction { Up, Down, Left, Right, } let directions = [ Direction.Up, Direction.Down, Direction.Left, Direction.Right, ]; // transpile let directions = [ 0 /* Direction.Up */, 1 /* Direction.Down */, 2 /* Direction.Left */, 3 /* Direction.Right */, ];
transpile 시 단순히 enum을 사용하는 것과 달리 불필요한 부분이 없어졌고 이를 통해 Reverse mappings이 일어나지 않고 IIFE가 없어 Tree Shaking에도 이슈가 없습니다. 하지만 const enum은 babel로 transpile 할 수 없고 TypeScript의 설정에 따라 const enum이 제대로 동작을 안 할 수 있습니다.
as const
type assertion을 사용하여 as const를 통해 상수를 지정합니다.
const Direction = { Up: 0, Down: 1, Left: 2, Right: 3, } as const; type Direction = typeof Direction[keyof typeof Direction]; // transpile const Direction = { Up: 0, Down: 1, Left: 2, Right: 3, };
as const를 사용하면 앞서 확인했던 TypeScript Enums의 문제점인 Reverse mappings, Tree Shaking 이슈, TypeScript 설정에 따른 이슈 없이 사용할 수 있습니다.
마무리
여러 레퍼런스를 참고하거나 TypeScript Enums에서 enum과 const enum 그리고 as const를 직접 확인했을 때 아래와 같은 순서로 상수 지정 방식을 선택할 수 있습니다.
as const > const enum > enum
TypeScript Handbook에서도 해당 내용을 볼 수 있습니다.
In modern TypeScript, you may not need an enum when an object with as const could suffice
TypeScript를 사용하며 단순히 상수를 지정하는 방식에서도 많은 효율을 올릴 수 있음을 알 수 있습니다. 사소한 부분도 신경을 쓰며 개발해야겠습니다.
참고 자료
https://www.typescriptlang.org/ko/docs/handbook/enums.html
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
https://velog.io/@logqwerty/Enum-vs-as-const
https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking