Getting the enum key with the value string (reverse mapping) in TypeScript

typescript get value of enum key
javascript enum get key by value
get enum key from value
computed values are not permitted in an enum with string valued members.
typescript enum in class
es6 enum
typescript extend enum
typescript map enum

I have an enum:

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

I have a function with the enum as a parameter:

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

I am calling the function like that:

responseOK(ApiMessages.logged_ok, {user: userRes})

I am trying to return the enum key and the enum string value to the response but I get the TS error:

TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

I have strict TypeScript config. Adding suppressImplicitAnyIndexErrors is not an option.

TypeScript version: 2.9.2

As described in the handbook:

Keep in mind that string enum members do not get a reverse mapping generated at all.

That means there is no simple reverse mapping in your case.

Workaround: Getting a reverse mapping for string enum members

To get the key of an enum member by it's value, you have to iterate through the enum keys and compare the associated value with your target value.

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

Some demo code follows. You can also see it in action on the 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;
}

Adding this into your responseOK() you end up with:

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

Handbook - Enums, We know that num values can be retrieved using the corresponding enum member value. But it is also true that enum members can be retrieved using their values. This is called reverse mapping. TypeScript can compile the above enum into the following JavaScript function. In this generated code, an enum is compiled into an object that stores both forward (name -> value) and reverse (value -> name) mappings. References to other enum members are always emitted as property accesses and never inlined. Keep in mind that string enum members do not get a reverse mapping generated at all.

You can easily create a map that allows you to get the key from the value without creating a special function for it.

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'

Enum in TypeScript, My TypeScript Version is 2.7.1 enum Country{ India = "INR", France = "EUR", In Line 9, the reverse mapping is not working for string based enum. then you'd have no way to distinguish keys from values unless there was a� # No Reverse Mapping for String-Valued Enum Members TypeScript emits some mapping code for each enum which constructs a mapping object. For string-valued enum members, this mapping object defines mappings from key to value, but not vice versa:

For those who come looking as I did, this works for me.

NOTE: This is only valid if you know that your string value is a valid 'key'.

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

const str: string = 'apple';

const fruit = str as Fruit;

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

if (fruit === Fruit.Bananna)
    console.log("It's a bananna");

String Based Enum, It is now possible to assign a string value to an enum member: this case, the compiler additionally emits a reverse mapping from value to key: PrintMedia is an object in JavaScript which includes both value and name as properties and that's why enum in TypeScript supports reverse mapping. So, both the following mappings are true to enums: name -> value, and value -> name.

String Enums in TypeScript — Marius Schulz, Explore the ins and outs of enums in TypeScript, including their types and properties, constants in enums, computed enums, and even reverse mapping. This means that they can store string values as numbers. to the first member, we still get sequential incrementation by one for the rest of the members. As you see enum object is used to store two types of values - one type stores index and enum strings, other type stores reverse of data like string and enum. By default, each enum constants is assigned with numbers starting from 0,1 ie. Sunday=0, Saturday=1 defined enumeration with initializing string values

Writing readable code with TypeScript enums, typescript string enum reverse mapping typescript string to enum angular enum in template typescript enum in class javascript enum get key by value typescript� Reverse mapping. TypeScript enums support reverse mapping, which simply means that just as we have access to the value of an enum member, we also have access to the enum name itself. A sample of our first demonstration is used to portray this below:

Reverse mapping string enum angular 4, In TypeScript enum elements can also be assign to string values (instead of numeric values): enum NumSymbol { K = 'kilo', M = 'mega',� For string enum, you can get the name directly by iterating enum through for loop because string enums directly store key value pairs in enum object.

Comments
  • Hi. In your example message is the value of the enum and not the key. So message is Logged OK and your messageId would be undefined. Btw, messageId is in your example not a number
  • ApiMessages.logged_ok === 'Logged OK'. in your function message is the string you want to send as the message. ApiMessages.logged_ok is the actual value of enum already!
  • Oh, good to know. Thank you very much for the detailed answer and the demo. The workaround works like a charm.
  • For me, this one seems to be the accurate answer, however, should be stated that "There's no reverse mapping".
  • Hi @RooticalV., can you explain what you mean by "there's no reverse mapping"?