如何在Typescript中通过值获取枚举键?

91

我有一个枚举类型如下:

export enum Colors {
    RED = "RED COLOR",
    BLUE = "BLUE COLOR",
    GREEN = "GREEN COLOR"
}

您好,请问如何通过值获取枚举键呢?例如,我需要传递“蓝色”并获取“BLUE”。

Colors["BLUE COLOR"]会出现错误:元素隐式具有'any'类型,因为类型为'"BLUE COLOR"'的表达式无法用于索引类型'typeof Colors'。 在类型“typeof Colors”上不存在属性“BLUE COLOR”。


https://www.codegrepper.com/code-examples/typescript/angular+print+enum+value - firstpostcommenter
这个答案对我来说是最有帮助的(getEnumKeyByEnumValue):https://stackoverflow.com/a/73681064/470749 - undefined
9个回答

72
如果您想通过枚举值获取枚举键,那么您需要按以下方式重写枚举。但同样的格式在旧版本中也可能起作用。对于纯JavaScript,应该像下面这样:
 enum Colors {
    RED = "RED COLOR",
    BLUE = "BLUE COLOR",
    GREEN = "GREEN COLOR"
}

对于 .tsx 文件,应该像下面这样:

 enum Colors {
        RED = "RED COLOR" as any,
        BLUE = "BLUE COLOR" as any,
        GREEN = "GREEN COLOR" as any
    }

对于.ts文件应该像下面这样:

enum Colors {
  RED = <any>"RED COLOR",
  BLUE = <any>"BLUE COLOR",
  GREEN = <any>"GREEN COLOR"
}

那么您可以按照以下方法进行操作:

通过值检索枚举键:

let enumKey = Colors["BLUE COLOR"];
    console.log(enumKey);

输出:

enter image description here

另一种方式:根据值检索枚举键:

let enumKey = Object.keys(Colors)[Object.values(Colors).indexOf("BLUE COLOR")];

console.log(enumKey);

输出:

enter image description here

在 jsfiddle 上测试:

jsfiddle 上的代码示例

注意: TypeScript 4.8 于 8 月 25 日发布了新公告。请注意。 您可以在此处查看。


41
这个答案为什么有效?'any' 如何实现“反向查找”?谢谢。 - New Alexandria
9
出现错误:在具有字符串值成员的枚举中不允许使用计算值。 - Kristoffer Tølbøll
请您查看此链接(https://github.com/microsoft/TypeScript/issues/27976)。希望它能对您有所帮助。 - Md Farid Uddin Kiron
3
如Dedi所述,此答案已不再适用。 - akcasoy
1
这太棒了。我应该早点发现它。 - Changdae Park
显示剩余13条评论

51

26

我正在使用这个函数

export function getEnumKeyByEnumValue(myEnum: any, enumValue: number | string): string {
  let keys = Object.keys(myEnum).filter((x) => myEnum[x] == enumValue);
  return keys.length > 0 ? keys[0] : '';
}

Jest测试

describe('enum', () => {
  enum TestEnumWithNumber {
    ZERO
  }

  enum TestEnumWithString {
    ZERO = 'ZERO'
  }

  it('should return correct key when enum has number values', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithNumber, TestEnumWithNumber.ZERO);
    expect(key).toBe('ZERO');
  });

  it('should return correct key when enum has string values', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithString, TestEnumWithString.ZERO);
    expect(key).toBe('ZERO');
  });

  it('should return correct key by passing corresponding string value', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithString, 'ZERO');
    expect(key).toBe('ZERO');
  });
});

希望能帮助到某些人


我喜欢这个答案,但是不使用“any”函数是否也有可能? - Aaron Hill
@AaronHill 我不知道除了any之外还有什么其他的办法能够起作用。 - Nux
我非常喜欢单元测试,不过,如果KEY和VALUE不同的话,你的最终单元测试会更好。例如,将值更改为字符串'0',并保持键为'ZERO',以证明传递值可以检索键。现在的情况是,你的方法可能只是返回带有'ZERO'作为表示键的参数的值,你的测试就无法证明其他情况。 - undefined

16

不使用任何方式来改进getEnumKeyByEnumValue

export function getEnumKeyByEnumValue<
  TEnumKey extends string,
  TEnumVal extends string | number
>(myEnum: { [key in TEnumKey]: TEnumVal }, enumValue: TEnumVal): string {
  const keys = (Object.keys(myEnum) as TEnumKey[]).filter(
    (x) => myEnum[x] === enumValue,
  );
  return keys.length > 0 ? keys[0] : '';
}


7

试试这样做

enum Colors
{
   RED = "RED COLOR",
   BLUE = "BLUE COLOR",
   GREEN = "GREEN COLOR"
};   

 console.log(Object.keys(Colors)[Object.values(Colors).indexOf('BLUE COLOR' as unknown as Colors)]);

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

3

通过添加类型检查改进了getEnumKeyByEnumValue:

enum Colors {
    RED = "RED COLOR",
    BLUE = "BLUE COLOR",
    GREEN = "GREEN COLOR"
}

type ValueOf<T> = T[keyof T];

function getEnumKeyByEnumValue<R extends (string | number), T extends {[key: string] : R}>(myEnum: T, enumValue: ValueOf<T>): string {
  let keys = Object.keys(myEnum).filter((x) => myEnum[x] == enumValue);
  return keys.length > 0 ? keys[0] : '';
}



let enumKey = getEnumKeyByEnumValue(Colors, Colors.RED);

// next line will trigger: Argument of type '"OTHER COLOR"' is not assignable to parameter of type 'ValueOf<typeof Colors>'.
//let enumKey = getEnumKeyByEnumValue(Colors, "OTHER COLOR");

console.log(enumKey);

https://jsfiddle.net/2ry1u8qb/


2

我想稍微修正一下代码:

return Object.keys(myEnum).find(x => myEnum[x] === enumValue);

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community
无法处理我的字符串值枚举: TS7053:元素隐式具有'any'类型,因为'typeof MyEnum'类型上找不到带有'typestring'参数的索引签名。 'MyEnum'类型上没有找到参数为'string'的索引签名。 - PatrykMilewski

1
你可以这样获取枚举键:
enum Colors {
    RED = "RED COLOR",
    BLUE = "BLUE COLOR",
    GREEN = "GREEN COLOR"
}

for (let item in Colors) { 
    if (Colors[item] === "BLUE COLOR") { 
        alert(item)
    }
}

8
但我想这可能有点昂贵且嘈杂。 - Md Farid Uddin Kiron
这取决于您的需求。 - Emanuele Scarabattoli

1
每个人都在分享运行时解决方案,但如果你想要一个TypeScript解决方案,这里就是它:
enum EXAMPLE_ENUM {
    KEY_ONE = 'Value One',
    KEY_TWO = 'Value Two'
}

// Result:
// type ReverseEnum = {
//     readonly "Value One": "KEY_ONE";
//     readonly "Value Two": "KEY_TWO";
// }
type ReverseEnum = {[K in keyof typeof EXAMPLE_ENUM as typeof EXAMPLE_ENUM[K]]: K}

// Result:
// type EnumKeyFromValue = EXAMPLE_ENUM.KEY_ONE
type EnumKeyFromValue = typeof EXAMPLE_ENUM[ReverseEnum['Value One']]

首先创建一个类型,用于交换枚举的键和值的位置(ReverseEnum)。
通过使用typeof枚举,它允许您以字符串形式对枚举的键进行索引访问。然后,您可以使用反转的枚举类型获取该键的名称。
它可以完美地与值字符串的自动完成等一切工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接