news 2026/1/22 16:03:02

TypeScript 里最糟糕的功能是 Enum(而且它坑得很“安静”)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TypeScript 里最糟糕的功能是 Enum(而且它坑得很“安静”)

我有一支技术全面、经验丰富的小型团队,专注高效交付中等规模外包项目,有需要外包项目的可以联系我

问题在这: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:

  1. 你确实需要运行时查表 / 映射(而不是单纯限定值)

  2. 你能控制系统两端(前端 + 后端/服务端)并且约定一致

否则?

扔掉。

如果你的“枚举”不需要在运行时存在,那就别让它存在。 用 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技巧合集

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/14 8:49:57

QQ空间历史说说完整备份指南:永久保存你的青春记忆

QQ空间历史说说完整备份指南:永久保存你的青春记忆 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 还在为那些承载着珍贵回忆的QQ空间说说可能丢失而烦恼吗?那些…

作者头像 李华
网站建设 2026/1/5 10:43:18

告别无效检索:我用LangExtract + Milvus升级 RAG 管道的实战复盘

今天我们聊下Google 的新开源库 LangExtract。虽然他已经开源了一段时间。但这段时间我一直在实际项目里用它,踩了不少坑,也总结了一些经验。所以,这篇文章不打算讲太多理论,咱们直接上代码,聊实践。 如果你和我一样&a…

作者头像 李华
网站建设 2026/1/14 5:13:52

iOS系统深度定制完全指南:Cowabunga Lite全方位操作手册

iOS系统深度定制完全指南:Cowabunga Lite全方位操作手册 【免费下载链接】CowabungaLite iOS 15 Customization Toolbox 项目地址: https://gitcode.com/gh_mirrors/co/CowabungaLite 想要让你的iPhone界面焕然一新却不想冒险越狱?iOS系统个性化定…

作者头像 李华
网站建设 2026/1/14 12:24:47

如何用League Director制作专业级英雄联盟回放视频

如何用League Director制作专业级英雄联盟回放视频 【免费下载链接】leaguedirector League Director is a tool for staging and recording videos from League of Legends replays 项目地址: https://gitcode.com/gh_mirrors/le/leaguedirector 想要制作出媲美职业联赛…

作者头像 李华