← 返回题目列表

TypeScript enum 和字面量联合类型怎么选?

高频 中等 第 20 / 32 题 更新于 2026/07/29
TypeScriptenum联合类型

简化版

enum 会生成运行时代码,适合需要运行时对象、反向映射或跨模块复用常量的场景;字面量联合类型只存在于类型层,更轻量,适合前端状态、配置值和 API 字段约束。现代前端更常用联合类型配合 as const

详细版

示例:

enum Role {
  Admin = 'admin',
  User = 'user',
}

type Role2 = 'admin' | 'user';

选择思路:

  • 只做类型约束:优先字面量联合类型。
  • 需要运行时枚举对象:可以用 enumas const 对象。
  • 对包体积敏感:联合类型更轻。
  • 需要和后端常量对齐:字符串枚举或 as const 对象更直观。

面试重点是:enum 有运行时,联合类型只在编译期。

完整版教学

一、先看它们是否会出现在运行时

TypeScript 类型大多会在编译后擦除。 字面量联合类型就是纯类型,运行时不存在。 普通 enum 不同,它会被编译成 JavaScript 对象。

type Status = 'pending' | 'success' | 'failed';

enum StatusEnum {
  Pending = 'pending',
  Success = 'success',
  Failed = 'failed',
}

如果只需要限制变量只能取 3 个字符串,联合类型足够。 如果运行时要遍历所有可选项,enum 或常量对象才有实体可用。

二、数字 enum 有反向映射,字符串 enum 没有

数字枚举编译后会生成值到名字、名字到值的双向映射。 字符串枚举通常只有名字到值。 这也是数字枚举包体积和行为更复杂的原因。

enum Direction {
  Up,
  Down,
}

console.log(Direction.Up); // 0
console.log(Direction[0]); // "Up"

数字例子里 Up0Direction[0] 又能拿回 "Up"。 这在某些调试场景方便,但前端业务状态很多时候更希望值本身就是清晰字符串。

三、联合类型更适合前端状态字段

前端常见状态如按钮尺寸、主题、接口状态、组件 variant。 这些值通常来自字符串,运行时不需要一个枚举对象。 联合类型轻量、直观、和 JSON 字段天然一致。

type ButtonSize = 'small' | 'middle' | 'large';

function Button(props: { size: ButtonSize }) {
  return props.size;
}
维度enum字面量联合类型
运行时代码
包体积可能增加无额外输出
API 字符串字段可用很适合
遍历可选项方便需要配合数组或对象

很多 UI 组件库更倾向用联合类型描述 props。

四、as const 对象常用来替代 enum

如果既想要运行时对象,又想要类型推导,可以用 as const。 它能把对象值收窄成字面量类型。 再通过索引访问类型得到联合类型。

const Role = {
  Admin: 'admin',
  User: 'user',
} as const;

type Role = typeof Role[keyof typeof Role];

流程如下:

运行时对象 Role
  -> as const 固定字面量
  -> typeof Role 拿类型
  -> keyof typeof Role 拿 key
  -> 索引访问得到 value 联合

这套写法是现代前端工程里非常常见的 enum 替代方案。

五、const enum 要谨慎

const enum 会在编译时内联,通常不生成枚举对象。 它能减少运行时代码,但在 Babel、isolatedModules、库发布场景下容易遇到兼容问题。 如果配置链路不完全由 TypeScript 编译器处理,要特别小心。

const enum Code {
  Ok = 200,
  NotFound = 404,
}

const ok = Code.Ok; // 可能被内联成 200

记忆钩子:enum 像运行时常量表,联合类型像编译期取值范围。

项目内部可控时可以使用 const enum。 对外发布类型包或多工具链项目中,更推荐联合类型或 as const 对象。

六、工程选择建议

如果团队主要写前端业务和组件库,默认选择字面量联合类型。 如果需要运行时遍历选项,使用 as const 对象。 如果和后端或历史代码已经大量使用 enum,可以继续使用字符串 enum,但要理解运行时代码成本。

const STATUS_OPTIONS = ['pending', 'success', 'failed'] as const;
type Status = typeof STATUS_OPTIONS[number];

这个写法只有 1 份运行时数组,同时能得到类型。 适合表单选项、筛选项、状态列表。

七、常见误区与追问

  • 误区:enum 只是类型,不会生成代码。 普通 enum 会生成运行时代码,联合类型才会被擦除。
  • 误区:数字 enum 和字符串 enum 行为完全一样。 数字 enum 有反向映射,字符串 enum 通常没有。
  • 误区:const enum 永远更好。 它依赖编译链路,库发布和 Babel 场景要谨慎。
  • 追问:为什么前端组件 props 常用联合类型? 它轻量、直观、无运行时代码,能直接约束字符串取值。
  • 追问:如何既有运行时对象又有类型? 使用 as const 对象或数组,再通过 typeof 推导联合类型。
  • 追问:enum 适合什么场景? 适合需要运行时枚举对象、跨模块常量表或历史系统统一常量的场景。

八、加强记忆

选型时先问一句:运行时需不需要这个常量表。需要就考虑 enumas const,不需要就用联合类型。现代前端常用“as const 数据源 + 推导联合类型”的方式,同时兼顾运行时和类型层。