Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

typescript

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

like image 953
miqrc Avatar asked Jan 21 '19 20:01

miqrc


People also ask

Does TypeScript have enums?

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

What is enum ts?

In TypeScript, enums, or enumerated types, are data structures of constant length that hold a set of constant values. Each of these constant values is known as a member of the enum. Enums are useful when setting properties or values that can only be a certain number of possible values.


2 Answers

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 its 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; } 

You can type this more strictly as follows (note that we can interpret our enum as an indexable type with key and value both being strings here):

function getEnumKeyByEnumValue<T extends {[index:string]:string}>(myEnum:T, enumValue:string):keyof T|null {     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<T extends {[index:string]:string}>(myEnum:T, enumValue:string):keyof T|null {     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     }; } 
like image 158
Søren D. Ptæus Avatar answered Sep 26 '22 02:09

Søren D. Ptæus


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' 
like image 40
Troy Weber Avatar answered Sep 26 '22 02:09

Troy Weber