enums와 const enums는 다르다. (reverse mapping)
const enum은 내부 상수값들이 전부 compile 단계에서 내부 필드를 전부 상수로 변경하기 때문에 런타임에 의존 모듈의 영향을 받지 않게 되며, 코드 크기가 더 적기 때문에 더 선호된다고 한다.
구체적으로 어떻게 컴파일 되는지 보면 다음과 같다.
enum Bool {
True,
False,
FileNotFound
}
let value = Bool.FileNotFound;
var Bool;
(function (Bool) {
Bool[(Bool["True"] = 0)] = "True";
Bool[(Bool["False"] = 1)] = "False";
Bool[(Bool["FileNotFound"] = 2)] = "FileNotFound";
})(Bool || (Bool = {}));
let value = Bool.FileNotFound;
상당히 코드가 길어졌다. 무엇보다 (function ())() 꼴로 컴파일 된 것이 보이시는가?
Typescript에서 Enum은 즉시 실행 함수(IIFE)로 구현되기 때문에 트리 쉐이킹이 불가능해진다.
반면 const Enum을 사용하면 다음과 같이 컴파일 시점에 상수로 치환된다.
const enum Bool {
True,
False,
FileNotFound
}
let value = Bool.FileNotFound;
let value = 2; /* FileNotFound */
이렇게 보면 '잉? const Enum이 더 좋은거 아니냐?'라고 생각할 수 있지만 그렇지 않다.
타입스크립트를 사용한다면 대개 프론트 프레임워크 내부에서 사용하거나, 패키지를 만들 때 사용할텐데 이 경우에는 값이 상수로 치환된다면, 타이핑 자체가 불가능해진다. 이런 상황을 막기 위해 tsconfig에서 isolatedModules 옵션을 true로 설정하곤 한다.
용량에 그렇게 민감하다면 const Enum보다 as Const를 사용해보도록하자.
아래와 같은 꼴로 Enum을 흉내낼 수 있고, 컴파일된 후의 용량도 Enum에 비해 작은 편이다.
export const Country = {
US: 'us',
CA: 'ca',
AU: 'au',
KR: 'kr',
};
export type COUNTRY = typeof Country[keyof typeof Country];
React, Next 등 프레임워크에서는 무엇을 쓰면 좋은가
우선 Next에서 Enum, as const 둘 다 써봤는데 빌드까지 잘 된다.
취향이지만, 다음과 같은 기준으로 사용하면 되겠다.
- 용량 거 얼마나 나간다고, 빠른 생산성 추구 => Enum
- 용량을 가급적 줄여야 하는 경우 => as const
- CRA bolerplate나 Next를 사용한다면 => const Enum 사용 불가. 사용하게 ‘될 경우 const enums are not supported 에러
- const enum이 용량을 줄이는 건 어차피 isolatedModules 옵션을 활성화하게 되면 의미가 없어지므로 유의
- 여러분들이 만약 TS 기반 패키지를 만든다면 isolatedModules을 활성화하고, const Enum을 사용하지 말아야 한다. 컴파일되어서 정적값이 되었는데 그걸 사용자가 타입용으로 사용할 수는 없지 않은가?
reference)
https://ncjamieson.com/dont-export-const-enums/
https://jaeyeophan.github.io/2018/06/16/TS-8-enum-vs-const-enum/
engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/
https://velog.io/@logqwerty/Enum-vs-as-const
'Programming Language > 🟦 Typescript' 카테고리의 다른 글
Dependency Injection(의존성 주입) in Typescript (0) | 2021.04.27 |
---|---|
window 객체 extends하기 (0) | 2021.04.04 |
typescript에서 DOM 다루기 (0) | 2021.03.01 |
Mapped Type (0) | 2021.03.01 |
@Decorator (3) : reflect-metadata (0) | 2021.01.13 |