enum
(枚举)是 TypeScript 中一个非常实用的语言特性,用于定义一组有名字的常量。它在 JavaScript 中并没有直接对应的原生语法,因此编译器需要将其转化为 JavaScript 可执行的形式。本文将介绍 TypeScript 中各种类型的 enum
是如何被转译成 JavaScript 代码的。
一、普通的数字枚举(Number Enum)
TypeScript
enum Direction {
Up,
Down,
Left,
Right
}
编译后的 JavaScript(ES5)代码:
JavaScript
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 = {}));
原理解析:
- TypeScript 使用 立即调用函数表达式(IIFE) 创建一个对象
Direction
。 - 枚举成员不仅有 从名称到数值 的映射,如
Direction.Up === 0
; - 还有 从数值到名称 的反向映射,如
Direction[0] === "Up"
。 - 这就是所谓的 双向映射(Bidirectional Mapping)。
二、带初始值的枚举
TypeScript
enum Status {
Ok = 200,
NotFound = 404,
Error = 500
}
编译结果:
JavaScript
var Status;
(function (Status) {
Status[Status["Ok"] = 200] = "Ok";
Status[Status["NotFound"] = 404] = "NotFound";
Status[Status["Error"] = 500] = "Error";
})(Status || (Status = {}));
- 如果第一个枚举成员提供了初始值,其余成员会自动递增(如果没有指定值)。
- 不影响双向映射机制。
三、字符串枚举(String Enum)
TypeScript
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
编译结果:
JavaScript
var Color;
(function (Color) {
Color["Red"] = "RED";
Color["Green"] = "GREEN";
Color["Blue"] = "BLUE";
})(Color || (Color = {}));
注意:
- 字符串枚举只生成 单向映射 :
Color.Red === "RED"
; - 无法通过
Color["RED"]
获取Red
,也无法做反向映射。
四、Heterogeneous Enum(混合型枚举)
TypeScript
enum Result {
Yes = 1,
No = "NO"
}
编译后:
JavaScript
var Result;
(function (Result) {
Result[Result["Yes"] = 1] = "Yes";
Result["No"] = "NO";
})(Result || (Result = {}));
- 混合型枚举不是很推荐使用;
- 可能会导致代码混淆,尤其是需要一致性的时候。
五、常量枚举(const enum
)
TypeScript
const enum Axis {
X,
Y,
Z
}
const dir = Axis.X;
编译后的 JavaScript:
JavaScript
var dir = 0 /* X */;
特点:
- 不生成任何枚举对象代码;
- 所有对枚举成员的引用都被直接替换为对应的值;
- 更适合性能敏感或体积敏感的场景;
- 但是不能用于需要运行时访问枚举对象的情况。
六、如何查看枚举转译后的 JavaScript?------使用 TypeScript Playground
想要直观地查看 TypeScript 枚举是如何被编译为 JavaScript 的代码,可以使用 TypeScript 官方提供的在线工具 ------ Playground:
访问地址:
👉 www.typescriptlang.org/play/
使用方法:
-
打开 Playground 页面;
-
在左侧编辑器中输入你的 TypeScript 枚举代码,例如:
TypeScript
enum Direction {
Up,
Down,
Left,
Right
}
console.log(Direction)
- 右侧就会自动显示编译后的 JavaScript 代码,默认是 ES5 模式;

console.log(Direction)
的输出如下图所示:

-
你还可以通过点击上方的 "TS Config" 下拉按钮,选择不同的目标版本(如 ES3、ES5、ES6);
-
如果你使用了
const enum
,记得关闭isolatedModules
或开启preserveConstEnums
才能查看其替换行为。
小贴士:
- Playground 是调试 TypeScript 特性最简单有效的方式;
- 除了枚举,也适用于泛型、装饰器、类型推导等各种高级语法的编译分析;
- 它还能分享代码片段,只需点击右上角的 "Share" 按钮,即可生成链接。
七、编译选项影响
- 如果开启了
--preserveConstEnums
,const enum
会保留为实际的 JavaScript 枚举对象; - 如果关闭
--isolatedModules
,可以使用const enum
; - 编译为 ES6 时,枚举仍然是 var + IIFE 模式,并不会转化为
const
+class
或Map
等。
八、小结
枚举类型 | 是否生成对象 | 是否支持反向映射 | 编译后体积 |
---|---|---|---|
数字枚举 | ✅ | ✅ | 一般 |
字符串枚举 | ✅ | ❌ | 一般 |
const 枚举 | ❌(直接替换) | ❌ | 最小 |
九、结语
TypeScript 的 enum
设计初衷是为了增强 JavaScript 的可读性和类型安全性,但它的转译方式也让我们理解了一个类型系统是如何在不支持这些语法的 JavaScript 上运行的。选择使用哪种枚举,应当根据运行时是否需要访问枚举值、是否需要反向映射、以及最终代码的体积要求进行权衡。