停止盲目地将 `enum` 替换为 `as const`

发布: (2026年3月13日 GMT+8 15:18)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Introduction

你可能已经看到很多文章建议我们用 as const 对象来替代 TypeScript 的 enum,理由包括:

  • 更好的 tree‑shaking
  • 更小的 bundle 大小
  • 更少的运行时代码

这些建议并非完全错误,但往往过于简化。
真正的问题不是“我们应该停止使用 enum 吗?”而是:我们是否了解 TypeScript 在幕后生成了什么代码,以及我们在做哪些权衡?

Numeric enums and the generated code

对于数字枚举,TypeScript 会生成额外的运行时代码。

enum Direction {
  Up,
  Down,
  Left,
  Right,
}

上述代码会被大致转译为下面的 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["Up"] = 0 赋值。该赋值返回 0,于是 TypeScript 还会设置 Direction[0] = "Up"

运行时我们得到的对象大致是:

{
  Up: 0,
  Down: 1,
  Left: 2,
  Right: 3,
  0: "Up",
  1: "Down",
  2: "Left",
  3: "Right"
}

这称为 反向映射

Direction.Up   // 0
Direction[0]  // "Up"

as const objects

现在把它和普通的 as const 对象进行比较:

const DirectionConst = {
  Up: "Up",
  Down: "Down",
  Left: "Left",
  Right: "Right",
} as const;

这只是一个普通的 JavaScript 对象,没有反向映射,也没有额外的运行时代码。因此,许多开发者发现 as const 在以下场景下非常有用:

  • 前端应用
  • 配置对象
  • 路由名称
  • 状态值
  • 动作类型
  • 其他以 JS 为主的模式

Enums aren’t “bad”

问题不在于枚举本身不好,而是很多人盲目地用 as const 替代它们,而没有考虑具体的使用场景。并非所有枚举都一样:

  • 数字枚举 会生成反向映射。
  • 字符串枚举 不会 生成反向映射。
  • const enum 有一套不同的权衡(它在编译时内联)。

as const 并不是每种枚举使用场景的 1:1 替代品。在替换之前,先问自己:

  • 我们需要反向映射吗?
  • 我们需要运行时的枚举对象吗?
  • 我们使用的是数字枚举还是字符串枚举?
  • 这是应用代码、库代码,还是协议/编译器风格的代码?
  • 我们是为了明确性、体积大小,还是 JavaScript 简洁性在优化?

Conclusion

as const 是一种很好的模式,枚举也并非天生错误。所谓的“高级做法”不是盲目跟随口号如“停止使用枚举”,而是要理解 TypeScript 的内部工作原理,并为具体的使用场景选择合适的工具。

0 浏览
Back to Blog

相关文章

阅读更多 »

关于 JavaScript 的简介

介绍 在今天的课堂上,我学习了 JavaScript 的简短介绍,所以我将在这篇博客中分享一些关于 JavaScript 的事实。什么是 JavaScript?JavaScr...

现代 JavaScript:理解 ES6 类

封面图片:Modern JavaScript:Understanding ES6 Classes https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%...