열거형은 키에 값을 할당하는, 순서가 없는 자료구조이다. 문자열에서 문자열로 매핑되거나 문자열에서 숫자로 매핑하는 열거형 이렇게 두 가지가 존재한다. 값을 명시하지 않는다면 타입스크립트는 자동으로 열거형의 멤버에 적절한 숫자(이전 값 + 1, default는 0)를 추론해 할당한다.
// 내가 작성한 코드
enum Language {
English,
Spanish,
Russian
}
// 타입스크립트가 값을 추론한 결과
enum Language {
English = 0,
Spanish = 1,
Russian = 2
}
// 내가 작성한 코드
enum Language {
English = 0,
Spanish = 500,
Russian
}
// 타입스크립트가 값을 추론한 결과
enum Language {
English = 0,
Spanish = 500,
Russian = 501
}
편리해보이는 enum은 크게 두 가지 문제점을 가진다.
타입스크립트의 enum은 키를 통해 값에 접근할 수도, 값을 통해 키에 접근할 수도 있다. 이는 불안정한 결과를 초래한다.
enum Color {
Red = '#c10000',
Blue = '#007ac1',
Pink = 0xc10050, // 16진수 리터럴
White = 255 // 10진수 리터럴
}
console.log(Color.Red) // '#c10000'
console.log(Color.Blue) // '#007ac1'
console.log(Color[255]) // 'White'
console.log(Color[0]) // undefined
console.log(Color[1]) // undefined
console.log(Color[2]) // undefined
타입스크립트는 존재하지 않는 값인 Color[0], Color[1], Color[2]
에 대한 접근을 막지 않는다.
불필요한 자바스크립트 코드를 발생시켜 tree-shaking을 방해한다.
enum은 타입스크립트가 자체적으로 구현하는 기능이다. 자바스크립트에서는 사용이 불가능하기 때문에 이를 자바스크립트에서도 사용하기 위해 불필요한 코드들이 작성된다.
+추가
https://github.com/microsoft/TypeScript/pull/15486
string 값만을 사용한다면 enum에서의 reverse mapping은 발생하지 않는다.
https://velog.io/@vraimentres/typescript-enum
enum을 사용하지 않는 것이 큰 개선은 아니다.
이러한 enum의 단점을 보완하는 기능이 const enum
이다.
const enum
은 enum
에서는 가능했던 역방향 찾기(값을 통해 키를 찾는 기능)를 지원하지 않는다. const enum
의 멤버는 문자열 리터럴로만 접근이 가능하다.
const enum Language {
English,
Spanish,
Russian
}
console.log(Language.English) // 0
console.log(Language.Spanish) // 1
console.log(Language[0]) // Error
또한 const enum
은 기본적으로 아무 자바스크립트 코드도 생성하지 않는다. 그 대신 필요한 곳에 열거형 멤버의 값을 채워 넣는다.
하지만, const enum
또한 분명한 단점들이 존재한다.
값을 채워넣는 const enum
의 방식이 문제를 일으킬 수 있다. const enum
의 값이 갱신되면 버전에 따라 다른 값을 갖게 되는 문제가 발생한다. 때문에 npm으로 배포하거나 라이브러리로 제공할 프로그램에서는 const enum
을 사용해서는 안된다.
CRA bolerplate나 Next를 사용한다면 const Enum
사용했을 때 에러가 난다고 한다.
tsconfig에서 isolatedModules
옵션을 true
로 설정하게 되면 enum
과 크게 차이가 없어진다.
enum
과 const enum
이 가진 문제들을 해결할 수 있는 기능이 const assertion
이다. 뒤에 as const
가 붙는다는 점을 빼면 자바스크립트에서 객체를 만드는 방식과 동일하다.
다만 const assertion을 사용할 때는 값을 생략할 수 없다.
마치 const assertion
이 최고인 것처럼 작성해놓았지만 팀의 선택에 맞추어 사용하면 될 것 같다.
https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/
https://www.typescriptlang.org/ko/docs/handbook/enums.html#objects-vs-enums
https://darrengwon.tistory.com/1310
타입스크립트 프로그래밍(프로그래밍 인사이트, 보리스 체르니 지음)