找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2025

积分

0

好友

287

主题
发表于 5 天前 | 查看: 9| 回复: 0

很多人眼里的 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 不是纯编译期产物——它会在JavaScript运行时真实存在。

这很怪。也很容易让人困惑。更容易让同事看着代码小声嘀咕一句:“这到底是什么鬼?”

现实一点:你根本不需要“运行时枚举”

我们说实话:你上一次真的需要 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. 你能控制系统两端(前端 + 后端/服务端)并且约定一致

否则?扔掉。

如果你的“枚举”不需要在运行时存在,那就别让它存在。用 as const 或字面量联合,你照样有类型安全,但不会引入混乱。

最后

enum 本来是来“带来秩序”的。结果它带来的更像是:官僚主义

它就像 TypeScript 里的“办公室中层”:总是不请自来,增加流程,让每个人都困惑一点点,然后还特别难删。

TypeScript 已经进化了。我们的习惯也该进化。

下次你想写 enum 的时候,停一秒,问问自己:“我是真的需要它,还是只是因为它看起来顺手?”

如果是后者——选 as const 或字面量联合类型。未来的你(以及你的队友)都会感谢你。

技术选型总是在权衡,而了解其潜在的性能开销与维护成本至关重要。如果你想探索更多关于现代前端开发的最佳实践和避坑指南,欢迎在云栈社区与其他开发者交流讨论。




上一篇:Spring Boot配置注解详解:@Configuration与@AutoConfiguration在应用开发与Starter封装中的区别
下一篇:Istio VirtualService 核心详解:路由规则、匹配条件与弹性治理
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-10 08:51 , Processed in 0.193649 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表