TypeScript 中的枚举(enum)有哪些类型?与普通对象有何区别?
1. 数字枚举
- 默认从 0 开始自动递增,也可以显式指定起始值
- 支持双向映射:既可以通过名称获取数值(Direction.Up 返回 0),也可以通过数值获取名称(Direction[0] 返回 "Up")
- 编译后生成一个包含正向和反向映射的 JavaScript 对象
- 风险:数字枚举的值在运行时只是数字,Direction.Up === 0 为 true,可能导致意外的类型混淆
2. 字符串枚举
- 每个成员必须显式指定字符串值
- 只有正向映射,没有反向映射
- 编译后的值是自描述的字符串,便于调试和序列化
- 更适合需要跨网络边界传输的场景,如 API 状态字段
3. const 枚举
- 使用 const enum 声明,编译时会将枚举值内联到每个使用位置
- 编译后不生成任何枚举对象,零运行时开销
- 限制:不支持反向映射,无法迭代枚举成员,与 isolatedModules 模式不兼容
- 现代构建工具(esbuild、SWC、Babel)默认启用 isolatedModules,因此 const enum 在这些环境中可能无法正常工作
4. 枚举与联合类型的对比
- 字符串字面量联合类型("PENDING" | "ACTIVE" | "CLOSED")提供相同的编译时类型安全,且编译后零运行时开销
- 联合类型不需要生成 JavaScript 对象,与 isolatedModules 完全兼容
- 枚举可以作为 switch 语句的判别字段,与联合类型配合使用
- 当需要运行时迭代枚举值或需要命名空间对象时,使用真正的枚举;否则优先使用联合类型
5. 异构枚举
- 技术上允许在同一个枚举中混合字符串和数字成员
- 例如 enum Mixed { No = 0, Yes = "YES" }
- 官方不推荐这种用法,因为语义不清晰且容易引起混淆