梗概

在TypeScript中,数字枚举支持从值到键的双向获取,但字符串枚举不支持这种双向映射。这是由于编译器生成代码的差异造成的。

数字枚举的双向获取

数字枚举天然支持双向映射:

enum NumericEnum {
  Up = 1,
  Down,
  Left,
  Right
}
 
// 从键到值
console.log(NumericEnum.Up);    // 输出: 1
console.log(NumericEnum.Down);  // 输出: 2
 
// 从值到键
console.log(NumericEnum[1]);    // 输出: "Up"
console.log(NumericEnum[2]);    // 输出: "Down"

字符串枚举的单向获取

字符串枚举只支持从键到值的单向映射:

enum StringEnum {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}
 
// 从键到值
console.log(StringEnum.Up);    // 输出: "UP"
 
// 从值到键 - 不支持
console.log(StringEnum["UP"]); // 输出: undefined

实现原理

TypeScript在编译数字枚举时会生成额外的反向映射代码:

// 编译后的数字枚举
var NumericEnum;
(function (NumericEnum) {
    NumericEnum[NumericEnum["Up"] = 1] = "Up";
    NumericEnum[NumericEnum["Down"] = 2] = "Down";
    // ...
})(NumericEnum || (NumericEnum = {}));

这种双重赋值的方式创建了双向映射关系。

字符串枚举的双向映射解决方案

如果需要字符串枚举的双向映射,可以自己实现工具函数:

function getEnumKeyByValue<T extends Record<string, string>>(
  enumObj: T,
  value: string
): keyof T | undefined {
  return Object.keys(enumObj).find(key => enumObj[key] === value) as keyof T | undefined;
}
 
console.log(getEnumKeyByValue(StringEnum, "UP")); // 输出: "Up"

使用建议

  • 需要双向映射时优先使用数字枚举
  • 字符串枚举更适合需要明确语义的场景
  • 避免在需要遍历的场景使用数字枚举(会产生双倍条目)

father:: ts 枚举 Enum 语法