TypeScript中enum、const enum及字符串联合类型的选用底层逻辑与场景问询
TypeScript 中 enum、const enum 与字符串联合类型的选型指南
什么时候该用普通 enum 而非 const enum?
普通enum相比轻量的const enum,核心优势是编译后保留了真实的JS对象,适合以下场景:
- 需要在运行时操作枚举的完整集合:比如遍历枚举生成表单下拉选项、批量校验入参是否属于合法枚举值、给枚举值映射多语言文案等,const enum编译后会被完全擦除,无法实现这类需求。
- 需要数字枚举的反向映射能力:普通数字枚举支持
Enum[Enum.VALUE] = 'VALUE'的反向映射,比如你从接口拿到一个数字状态码,直接就能反向查出来对应的枚举名,方便打日志和调试,这个能力是const enum和字符串联合都不具备的。 - 枚举作为公共API对外暴露:如果你是写工具库、组件库对外提供枚举,用const enum会导致枚举值被硬编码到依赖方的编译产物里,后续你修改枚举值时,依赖方如果不重新编译就会出现值不匹配的兼容性问题,普通enum因为是运行时真实对象就没有这个问题。
为什么很多人宁愿用普通 enum 也不用字符串联合类型?
就算不需要遍历能力,enum相对字符串联合的优势也很明显:
- 语义化分组更清晰:
OrderStatus.Paid比直接写'paid'可读性强得多,同一个业务域的常量被收拢在同一个枚举下,不会散落在代码各处,维护起来更方便。 - 编辑体验更好:输入枚举名+点号就能自动带出所有可选值,不用担心拼写错误,还可以给每个枚举成员加注释,hover 就能看到说明,字符串联合虽然也有提示,但没有分组的收拢感,很容易和其他同名字符串常量搞混。
- 支持数字枚举自动赋值:如果是数字类型的枚举,不需要挨个给成员赋值,TS会自动从0开始递增,后续加新成员也不用手动改值,字符串联合做不到这一点。
- 避免魔法值:代码里不会出现零散的字符串/数字字面量,后续要统一修改某个值的时候,只需要改枚举定义的一处就行,不用全局搜索替换。
不要毫无顾虑使用 const enum
const enum有几个很容易踩的坑:
- Babel原生不支持const enum,大部分React、Vue3项目如果用Babel做编译,要么会直接报错,要么会被自动转成普通enum,你预期的性能优化完全没生效。
- 如果tsconfig开启了
preserveConstEnums配置,const enum也会被编译成普通enum,和普通enum没有区别。 - 公共代码、跨包引用的场景用const enum会有兼容性风险,前面已经提到过。
字符串联合类型的优劣势
优点
- 编译产物完全没有额外代码,比const enum还要干净,完全不需要考虑tree-shaking的问题。
- 没有编译工具依赖,不管是TSC还是Babel都能正常支持,不会有兼容性问题。
- 和接口对接、跨语言协作的时候不需要做转换,字符串字面量直接和后端返回值对应。
缺点
- 没有运行时集合,要遍历所有可选值的时候需要单独维护一份常量数组,和类型定义重复,容易出现两边不一致的问题。
- 没有反向映射能力,拿到值之后没法反查对应的语义名称,调试的时候不方便。
- 语义分组弱,同一个业务域的可选值没有明确的归属,不熟悉代码的人很容易搞混不同业务域的同名字符串。
内容的提问来源于stack exchange,提问作者Phryxia
相关产品推荐
相关产品推荐

