在TypeScript中使用值字符串获取枚举键(反向映射)

miq*_*qrc 5 typescript

我有一个枚举:

export enum ApiMessages {
    logged_ok = 'Logged OK',
    register_ok = 'Register OK'
}
Run Code Online (Sandbox Code Playgroud)

我有一个带有枚举作为参数的函数:

export function responseOK(message: ApiMessages, result ?: any): ApiResponse {
    return {
        "status": "ok",
        "code": 200,
        "messageId": ApiMessages[message], <-- KO TS7015
        "message": message,
        "result": result
    };
}
Run Code Online (Sandbox Code Playgroud)

我正在这样调用函数:

responseOK(ApiMessages.logged_ok, {user: userRes})
Run Code Online (Sandbox Code Playgroud)

我试图将枚举键和枚举字符串值返回到响应,但出现TS错误:

TS7015:元素隐式地具有“ any”类型,因为索引表达式不是“ number”类型。

我有严格的TypeScript配置。不能添加excludeImplicitAnyIndexErrors。

TypeScript版本:2.9.2

Lee*_*son 22

如果您知道一个字符串(或任何其他值)是有效的枚举值,则可以告诉编译器将该值视为枚举。

注意:只有当您知道您的值对于枚举有效时,这才有效。

enum Fruit {
    Apple = 'apple',
    Bananna = 'bananna'
}

const str: string = 'apple';

const fruit: Fruit = str as Fruit;

if (fruit === Fruit.Apple)
    console.log("It's an apple");

if (fruit === Fruit.Bananna)
    console.log("It's a bananna");
Run Code Online (Sandbox Code Playgroud)

输出:It's an apple

  • 你是对的!我们只需要执行 `as MyEnum` 就可以了! (6认同)

Sør*_*æus 18

手册中所述:

请记住,字符串枚举成员根本不会生成反向映射。

这意味着您的情况没有简单的反向映射。

解决方法:为字符串枚举成员获取反向映射

要按其值获取枚举成员的键,您必须遍历枚举键,并将关联值与目标值进行比较。

function getEnumKeyByEnumValue(myEnum, enumValue) {
    let keys = Object.keys(myEnum).filter(x => myEnum[x] == enumValue);
    return keys.length > 0 ? keys[0] : null;
}
Run Code Online (Sandbox Code Playgroud)

一些演示代码如下。您还可以在TypeScript Playground上看到它的运行情况

enum ApiMessages {
    logged_ok = 'Logged OK',
    register_ok = 'Register OK'
}    

let exampleValue = ApiMessages.logged_ok;
let exampleKey = getEnumKeyByEnumValue(ApiMessages, exampleValue);

alert(`The value '${exampleValue}' has the key '${exampleKey}'`)


function getEnumKeyByEnumValue(myEnum, enumValue) {
    let keys = Object.keys(myEnum).filter(x => myEnum[x] == enumValue);
    return keys.length > 0 ? keys[0] : null;
}
Run Code Online (Sandbox Code Playgroud)

将其添加到您中responseOK()最终得到:

function responseOK(message: ApiMessages, result ?: any) {
    return {
        "status": "ok",
        "code": 200,
        "messageId": getEnumKeyByEnumValue(ApiMessages, message),
        "message": message,
        "result": result
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 我的编译器抱怨 myEnum 和 enumValue 隐式属于 any 类型。 (2认同)

Tro*_*ber 9

您可以轻松创建一个映射,该映射允许您从值中获取键,而无需为其创建特殊函数。

export enum ApiMessage {
    logged_ok = 'Logged OK',
    register_ok = 'Register OK'
}

export type ApiMessageKey = keyof typeof ApiMessage;

export const API_MESSAGE_KEYS = new Map<ApiMessage, ApiMessageKey>(
    Object.entries(ApiMessage).map(([key, value]:[ApiMessageKey, ApiMessage]) => [value, key])
)

API_MESSAGE_KEYS.get(ApiMessage.logged_ok); // 'logged_ok'
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这似乎是准确的答案,但是,应该指出“没有反向映射”。 (2认同)

sno*_*no2 8

您现在可以在 TypeScript 中获取类型中枚举的特征及其键

 enum ApiMessage {
    logged_ok = 'Logged OK',
    register_ok = 'Register OK'
}

// "logged_ok" | "register_ok"
type ApiMessageTraits = keyof typeof ApiMessage;

// "Logged OK" | "Register OK"
type MessageContents = `${ApiMessage}`;
Run Code Online (Sandbox Code Playgroud)

遗憾的是,这依赖于将可枚举项的键转换为字符串,因此除了字符串之外,您不能拥有任何其他类型的键。

编辑:通过使用带有 TypeScript 的模板文字大大简化了第二种方法>=4.1

  • 正是我正在寻找的,谢谢! (2认同)

Web*_*ber 5

简化版

枚举生成一个带有键值对的对象。
您真正需要做的就是找到正确的条目(如果有)。

所以,给出的例子

enum ApiMessages {
  Ok = 'OK',
  Forbidden = 'No access for you',
}

const example = ApiMessages.Forbidden;
Run Code Online (Sandbox Code Playgroud)

找到枚举条目

const match = Object.entries(ApiMessages).find(([key, value]) => value === example);
Run Code Online (Sandbox Code Playgroud)

选择键

if (match) {
  const [key] = match;
  console.log(`'${example}' matched key '${key}'.`);
}

// output: 'No access for you' matched key 'Forbidden'.
Run Code Online (Sandbox Code Playgroud)

就是这样。


在这里找到一个工作示例