枚举(enum)
本教程共 80 篇 · 第 12 篇 · 更新于 2026-08-10 · 约 12 分钟阅读
本节目标:理解枚举是什么、什么时候用,掌握数字枚举和字符串枚举的用法,了解
const enum的优化效果和官方立场,学会用联合字面量类型替代枚举。
枚举解决什么问题
写代码时经常要处理一组固定的常量——比如方向只有上下左右、订单状态只有待付款/已付款/已发货。用原始字符串或数字可以直接写,但容易出错:
// JavaScript 的写法:容易拼错
function move(direction: string) {
if (direction === "up") { /* ... */ }
}
move("Up"); // 大小写错了,静默失败
move("upp"); // 打错字了,静默失败
枚举把一组相关常量聚合成一个有名字的集合,让你用成员名代替裸值:
enum Direction {
Up,
Down,
Left,
Right
}
function move(direction: Direction) {
// direction 只能是 Direction 的成员
}
move(Direction.Up); // ✅ 编译器保证不会拼错
// move("Up"); // ❌ 字符串 "Up" 不是 Direction 类型
Note枚举是 TypeScript 少数几个不是纯类型层面的特性——它会产生运行时代码。这一点我们后面展开讲。
数字枚举
最简单的枚举。不赋值时,成员从 0 开始自动递增:
enum Color {
Red, // 0
Green, // 1
Blue // 2
}
console.log(Color.Red); // 0
console.log(Color.Green); // 1
console.log(Color.Blue); // 2
你也可以手动指定起始值,后续继续自动递增:
enum Status {
Success = 1,
Error, // 2
Pending // 3
}
console.log(Status.Pending); // 3
每个成员单独赋值也没问题:
enum HttpStatus {
OK = 200,
NotFound = 404,
InternalError = 500
}
// 也可以使用计算值
enum FileAccess {
Read = 1 << 1, // 2
Write = 1 << 2, // 4
ReadWrite = Read | Write // 6
}
反向映射
数字枚举有个特殊行为:可以从值反查键名。
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
console.log(Direction[0]); // "Up"
console.log(Direction[2]); // "Left"
编译成 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 = {}));
就是一个双向绑定的对象。反向映射在调试时很方便——打印数字就能看到对应的名称。
Note反向映射只有数字枚举支持。字符串枚举没有反向映射。
字符串枚举
字符串枚举每个成员都必须显式赋值,成员值是字符串而非数字:
enum Message {
Success = "SUCCESS",
Error = "ERROR",
Warning = "WARNING"
}
function handleMessage(msg: Message) {
switch (msg) {
case Message.Success:
console.log("操作成功");
break;
case Message.Error:
console.log("操作失败");
break;
case Message.Warning:
console.log("警告");
break;
}
}
handleMessage(Message.Success); // "操作成功"
字符串枚举的优点是可读性好——Message.Success 值就是 "SUCCESS",日志里看到这个字符串能一眼认出来。缺点是没有反向映射,也不支持自动递增。
实际项目中字符串枚举比数字枚举更常见,因为日志和网络传输时字符串比数字好理解。
异构枚举:数字和字符串混用
枚举里可以混合数字和字符串,但强烈不推荐:
enum Mixed {
No = 0,
Yes = "YES"
}
// 能跑通,但没人这么写——混淆了两种语义
计算成员 vs 常量成员
枚举成员分为两种:
常量成员:编译时就能确定值——包括字面量、对其他常量枚举成员的引用、常量表达式:
enum E {
A = 1, // 常量
B = 1 + 2, // 常量(常量表达式)
C = Math.random() // 计算成员(运行时才知道值)
}
计算成员没有反向映射能力,而且会让整个枚举变成”非 const”(不能用于 const enum 优化)。
const enum 和内部优化
在枚举前加 const 关键字,TypeScript 会把所有引用内联到代码里,完全消除运行时的枚举对象:
const enum Direction {
Up,
Down,
Left,
Right
}
let dir = Direction.Up;
// 编译后 → let dir = 0 /* Direction.Up */;
编译后的 JavaScript 中,Direction 对象不复存在,所有引用被替换成了字面量。这减少了代码体积和运行时开销。
🔴 关于 const enum 的官方立场
TypeScript 官方不推荐使用 const enum,该特性在未来版本可能被移除。
原因主要有两个:首先,const enum 的内联行为在跨项目导入时会出问题——如果使用方和定义方的枚举值不一致,类型检查可能漏出错。其次,Go 移植后的 7.0 编译器对 const enum 的支持有限,截至 7.0.2,官方尚未给出明确的 const enum 移除时间表。
// ❌ 官方不推荐
const enum Status {
Active,
Inactive
}
// ✅ 推荐替代:联合字面量类型
type Status = "active" | "inactive";
简单说:新项目不要引入 const enum。老项目中如果已经用了,留意官方后续动态。
用联合字面量类型替代枚举
枚举的很多场景可以用更轻量的联合字面量类型替代:
// 枚举写法
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
function move(dir: Direction) { }
// 联合字面量写法(推荐)
type Direction2 = "UP" | "DOWN" | "LEFT" | "RIGHT";
function move2(dir: Direction2) { }
move2("UP"); // ✅ 编辑器自动补全
// move2("upp"); // ❌ 编译错误
联合字面量的优势:
- 不产生运行时代码
- 更简洁,不需要 import
- 编辑器同样提供自动补全
- 完全类型安全
字符串枚举也不是一无是处——如果值需要在多处引用、或者需要遍历所有成员(Object.values(Status)),枚举仍然方便。
可运行示例
// 枚举综合示例
// 1. 数字枚举:订单状态
enum OrderStatus {
Pending = 0,
Paid = 1,
Shipped = 2,
Delivered = 3,
Canceled = 4
}
function getStatusText(status: OrderStatus): string {
switch (status) {
case OrderStatus.Pending: return "待付款";
case OrderStatus.Paid: return "已付款";
case OrderStatus.Shipped: return "已发货";
case OrderStatus.Delivered: return "已签收";
case OrderStatus.Canceled: return "已取消";
}
}
let order1 = OrderStatus.Paid;
console.log(`订单状态: ${getStatusText(order1)}`);
// 反向映射
console.log(`状态码 ${order1} 对应: ${OrderStatus[order1]}`);
// 2. 字符串枚举:日志级别
enum LogLevel {
Debug = "DEBUG",
Info = "INFO",
Warn = "WARN",
Error = "ERROR"
}
function log(level: LogLevel, message: string) {
console.log(`[${level}] ${message}`);
}
log(LogLevel.Info, "服务启动成功");
log(LogLevel.Error, "数据库连接失败");
// 3. 联合字面量:替代枚举的推荐方式
type Theme = "light" | "dark" | "auto";
function applyTheme(theme: Theme) {
console.log(`应用主题: ${theme}`);
}
applyTheme("dark");
// applyTheme("blue"); // ❌ 编译错误
输出:
订单状态: 已付款
状态码 1 对应: Paid
[INFO] 服务启动成功
[ERROR] 数据库连接失败
应用主题: dark
小结
枚举是 TypeScript 提供的一种聚合常量的机制。数字枚举支持反向映射,字符串枚举可读性更好。const enum 能减少代码体积但官方不推荐,新项目优先考虑联合字面量类型替代枚举。没有绝对的对错——小型项目或跨模块常量用联合字面量更清爽,需要遍历成员或频繁引用时枚举仍然是个好选择。下一章我们来看 any 和 unknown,以及它们对类型安全的不同影响。