我有一支技术全面、经验丰富的小型团队,专注高效交付中等规模外包项目,有需要外包项目的可以联系我
问题在这:Enum 不是“纯类型”,它是“会跑的东西”
很多人眼里的 enum,大概是这样:
enum Status { Pending, Approved, Rejected }看起来人畜无害,对吧? 但幕后真相是:TypeScript 会把它编译成一坨真实存在的 JavaScript 对象,类似这样:
"use strict"; var Status; (function (Status) { Status[Status["Pending"] = 0] = "Pending"; Status[Status["Approved"] = 1] = "Approved"; Status[Status["Rejected"] = 2] = "Rejected"; })(Status || (Status = {}));你没看错:一个“整洁的小枚举”,变成了双向映射对象。 所以你能这么玩:
Status.Approved; // 1 Status[1]; // "Approved"为什么要这样? 因为 TypeScript 的 enum不是纯编译期产物——它会在运行时存在。
这很怪。也很容易让人困惑。更容易让同事看着代码小声嘀咕一句:“这到底是什么鬼?”
现实一点:你根本不需要“运行时枚举”
我们说实话:你上一次真的需要 enum 的反向映射(Status[1] => "Approved")是什么时候?
大多数情况下:从来没有。
你需要的通常只是: 一组已知值——状态、角色、方向、颜色…… 你要的是“限定范围”,不是“运行时对象”。
那就别给自己加戏。用现代 TS 的方式:字面量联合类型或as const 对象。
例如这样:
const Status = { Pending: 'Pending', Approved: 'Approved', Rejected: 'Rejected' } as const; type Status = typeof Status[keyof typeof Status];你得到的是:
✅ 强类型约束 ✅ 自动补全 ✅ 没有诡异的运行时双向映射 ✅ 输出简单可预测
最爽的是: 这套模式几乎不会带来额外的运行时负担——类型信息是 TS 的魔法,编译后不会给你塞一坨“神秘对象”。
隐形成本:Enum 会“悄悄把项目带歪”
enum 最恐怖的地方不是它丑,而是它出问题时很阴,尤其在大代码库里。
1) 循环依赖:你会突然遇到 undefined 的惊喜
因为 enum 是真实的 JS 对象,所以当它在多个文件间被引入、再被引入,很容易就把你拖进循环依赖。
于是某天你会遇到: “咦?EnumName 怎么突然是 undefined?” 然后你开始排查半天,最后发现:是 import 顺序在搞你。
2) JSON / API 地狱:你到底传的是数字还是字符串?
把 enum 值丢到 JSON 里时,你会发现它可能是数字,也可能是字符串——取决于你写的是 numeric enum 还是 string enum。
下一秒,你的后端同事就会发来一句阴阳怪气的消息:
“为什么 status = 0,不是 'Pending'?你还好吗?”
然后你解释半天,最后大家一起浪费生命。
3) 代码不一致:数字枚举 + 字符串枚举混用 = 进入结界
你一旦在项目里混用 numeric enum 和 string enum,恭喜你:你踏进了一个“看似类型安全、实际越来越玄学”的区域。
你以为 TS 会拯救你。 结果 TS 只是在旁边看戏。
更简单的真相:你需要的是 Literal Types
enum 让人上头,是因为它看起来“结构化”。 但现代 TypeScript 的类型系统已经能让你结构化,而且不用背那一堆包袱。
比如直接写:
type Role = 'Admin' | 'User' | 'Guest'; function getAccessLevel(role: Role) { switch (role) { case 'Admin': return 'Full'; case 'User': return 'Limited'; default: return 'None'; } }没有运行时成本。 没有循环依赖。 没有“为什么变成数字”的鬼故事。 只有清爽、可读、可维护。
你不需要 enums。 你需要的是清晰。
我的经验法则
只有在满足这两个条件时,我才会考虑 enum:
你确实需要运行时查表 / 映射(而不是单纯限定值)
你能控制系统两端(前端 + 后端/服务端)并且约定一致
否则?
扔掉。
如果你的“枚举”不需要在运行时存在,那就别让它存在。 用 literal union 或 as const,你照样有类型安全,但不会引入混乱。
最后
enum 本来是来“带来秩序”的。 结果它带来的更像是:官僚主义。
它就像 TypeScript 里的“办公室中层”: 总是不请自来,增加流程,让每个人都困惑一点点,然后还特别难删。
TypeScript 已经进化了。 我们的习惯也该进化。
下次你想写enum的时候,停一秒,问问自己:
“我是真的需要它,还是只是因为它看起来顺手?”
如果是后者—— 选as const或字面量联合类型。 未来的你(以及你的队友)都会感谢你。
你怎么看? 你在生产环境还用 enum 吗?它有没有哪次把你坑到怀疑人生? 来,讲讲你的故事。
全栈AI·探索:涵盖动效、React Hooks、Vue 技巧、LLM 应用、Python 脚本等专栏,案例驱动实战学习,点击二维码了解更多详情。
最后:
CSS终极指南
Vue 设计模式实战指南
20个前端开发者必备的响应式布局
深入React:从基础到最佳实践完整攻略
python 技巧精讲
React Hook 深入浅出
CSS技巧与案例详解
vue2与vue3技巧合集