求求你不要再用TypeScript的枚举类型了

5,083 阅读1分钟

曾几何时,我也沉迷于 TypeScript 提供的枚举类型,有种高大上的感觉。但后来发现,其实枚举类型是「金玉其外,败絮其中」,请听我一一道来:

数值枚举类型不安全

我们定义一个非 0 即 1 的枚举类型如下:

enum ZeroOrOne {
  Zero = 0,
  One = 1,
}

然后给它赋一个不存在的值:

const zeroOrOne: ZeroOrOne = 2

结果 TypeScript 竟然没有报错!WTF?

WTF

字符串枚举无法直接赋值

我们定义一个字符串类型的枚举:

enum Color {
  Red = "Red",
  Green = "Green",
  Blue = "Blue",
} 

然后直接赋值:

const color: Color = "Red";

结果 TypeScript 竟然报错了!WTF?

WTF

算了,老子不用了!

还是用联合类型来替代枚举好了,例如:

const permissions = ['read', 'write', 'execute'] as const
type Permission = typeof permissions[number]

看到没,Permission 类型就是 'read' | 'write' | 'execute' 了呀,而且我们可以轻松遍历 permissions 数组:

for (const permission of permissions) {
  // 对 permission 为所欲为
}

想把对象的键/值拿出来做枚举?可以呀:

const Permission = {
  Read: "r",
  Write: "w",
  Execute: "x",
} as const;
type PermissionKey = keyof typeof Permission;
type PermissionValue = typeof Permission[PermissionKey];

看到没,PermissionKey 的类型就是 'read' | 'write' | 'execute' ,PermissionValue 的类型就是 'r' | 'w' | 'x' 了呀,而且我们可以轻松遍历 permissions 对象:

for (const permission of Object.keys(Permission)) {
  // 对 key 为所欲为
}
for (const permission of Object.values(Permission)) {
  // 对 value 为所欲为
}

让我们忘掉那些花里胡哨的语法,回归 JavaScript 最初的纯真美好吧!