Ways to retrieve the key of an enum based on its value within Typescript

Here's an example of an enum:

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

Can you help me figure out how to retrieve the enum key based on a specific value? For instance, if I input "BLUE COLOR", I should get back 'BLUE'.

Colors["BLUE COLOR"] triggers an error that says

Element implicitly has an 'any' type because expression of type '"BLUE COLOR"' can't be used to index type 'typeof Colors'. Property 'BLUE COLOR' does not exist on type 'typeof Colors'.

Answer №1

If you need to retrieve the enum key based on its value, you can modify your enum as shown below. This format should work in older versions as well.

For Basic JavaScript:

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

For .tsx:

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

For TypeScript (.ts):

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

You can then retrieve the key like this:

Retrieve enum key by value:

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

Output:

https://i.stack.imgur.com/M3b4n.gif

Another method to retrieve enum key by value:

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

console.log(enumKey);

Output:

https://i.stack.imgur.com/PZpu2.png

Check it out on jsfiddle:

View coding sample on jsfiddle

Note: A new announcement was made on August 25th with TypeScript 4.8. Please take note of it. Read more here.

Answer №3

I have implemented the following function

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] : '';
}

Testing with jest

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

  enum TestEnumWithString {
    ZERO = 'ZERO'
  }

  it('should correctly retrieve key for enums with number values', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithNumber, TestEnumWithNumber.ZERO);
    expect(key).toBe('ZERO');
  });

  it('should correctly retrieve key for enums with string values', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithString, TestEnumWithString.ZERO);
    expect(key).toBe('ZERO');
  });

  it('should correctly retrieve key by providing corresponding string value', function() {
    const key = getEnumKeyByEnumValue(TestEnumWithString, 'ZERO');
    expect(key).toBe('ZERO');
  });
});

Sharing in case it benefits someone

Answer №4

Enhanced version of getEnumKeyByEnumValue function without utilizing any:

export function retrieveEnumKeyByEnumValue<
  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] : '';
}

Answer №5

Give this a shot

enum Shades
{
   CRIMSON = "CRIMSON SHADE",
   INDIGO = "INDIGO SHADE",
   EMERALD = "EMERALD SHADE"
};   

 console.log(Object.keys(Shades)[Object.values(Shades).indexOf('INDIGO SHADE' as unknown as Shades)]);

Answer №6

Enhanced getEnumKeyByEnumValue function with type validations:

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);

// This line will result in an error: 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/

Answer №7

I want to make some adjustments to the code:

return Object.keys(ourEnum).find(y => ourEnum[y] === valueOfEnum);

Answer №8

If you want to retrieve enum keys in this way, you can use the following code snippet:

enum Shades {
    LIGHT = "LIGHT SHADE",
    DARK = "DARK SHADE",
    NEUTRAL = "NEUTRAL SHADE"
}

for (let value in Shades) { 
    if (Shades[value] === "DARK SHADE") { 
        console.log(value);
    }
}

Answer №9

While many are discussing runtime solutions, I have a Typescript solution to share:

enum NEW_ENUM {
    ITEM_ONE = 'First Item',
    ITEM_TWO = 'Second Item'
}

// Outcome:
// type FlippedEnum = {
//     readonly "First Item": "ITEM_ONE";
//     readonly "Second Item": "ITEM_TWO";
}
type FlippedEnum = {[F in keyof typeof NEW_ENUM as typeof NEW_ENUM[F]]: F}

// Outcome:
// type EnumValueFromKey = NEW_ENUM.ITEM_ONE
type EnumValueFromKey = typeof NEW_ENUM[FlippedEnum['First Item']]

Start by creating a type that swaps the positions of the keys and values in the enum. (FlippedEnum)

Using typeof with the enum allows indexed access into the keys of the enum as strings. Then, you can retrieve the name of that key using the flipped enum type.

This approach fully supports autocomplete for the value string and more.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why am I encountering this rendering issue when passing data to the ReactTable component?

The following code snippet represents the parent component containing an array of columns and data. const TransactionTable = () => { const columns = useMemo( () => [ { Header: 'DATE/TIME', accessor: &apos ...

Utilizing several data sources within a single mat-table

Hello, I require assistance with a task. I am trying to display multiple mat-tables with different data sources in my component.ts file Groups(){ this.apiSvc.Cards().subscribe((rsp: any) => { this.groups = rsp; this ...

Converting HTML templates into AMD modules using grunt-ts

When using the grunt-ts plugin and specifying the html: ["*.tpl.html"] option, it converts *.tpl.html files into *.tpl.html.js files at the end of the process, creating a global var. Is there a way to configure grunt-ts to output the final .js file in a d ...

Tips for dynamically loading a child component and passing data from the child component to the parent component

In my current setup, I have organized the components in such a way that a component named landing-home.component loads another component called client-registration-form.component using ViewContainerRef within an <ng-template>, and this rendering occu ...

What is the best way to utilize a union of interfaces in TypeScript when working with instances?

Review this TypeScript snippet: class A {public name: string = 'A';} interface B {num: number;} class Foo { get mixed(): Array<A | B> { const result = []; for (var i = 0; i < 100; i ++) { result.push(Mat ...

Finding a solution for duplicate date selections in NextJS using react-calendar

I am currently working on a calendar component using NextJS, typescript, tailwindcss, and the react-calendar library. I have encountered an issue with duplicate dates appearing in the calendar when selecting a date range. Although I have managed to handle ...

Unexpected behavior observed with Angular Toggle Button functionality

Having trouble implementing toggle functionality in Angular where different text is displayed when a button is toggled. I keep getting an error in my code, can anyone assist? See the code below: HTML <tr> <td>Otto</td> <td> ...

Angular2 - Actively selecting a checkbox in an ngFor loop with a reactive form

There is an object retrieved from a database that consists of a list of names with their corresponding IDs, as well as a flag to indicate whether they are selected or not. Object: let items = [{ ID: 1, Name: 'Item A', Selected: 'Y ...

Error encountered: ⨯ Compilation of TypeScript failed

My current project is utilizing Node.js in conjunction with TypeScript An issue has arisen during compilation within my Node.js application: E:\NodeProjects\esshop-mongodb-nodejs\node_modules\ts-node\src\index.ts:859 ret ...

Error: TypeError encountered during UI Runtime JSON conversion of Circular Data Structure

I'm facing an issue while attempting to parse and stringify certain JSON data. The error occurs on this specific line of code: this.copyOfColumns = JSON.parse(JSON.stringify(Object.assign([], this.columns))); Below is the complete @Input (using Ang ...

How can we direct the user to another tab in Angular Mat Tab using a child component?

Within my Angular page, I have implemented 4 tabs using mat-tab. Each tab contains a child component that encapsulates smaller components to cater to the specific functionality of that tab. Now, I am faced with the challenge of navigating the user from a ...

What steps should I take to fix the error "Unused left side of comma operator with no side effects.ts(2695)" in my React project?

import React from "react"; import { useRecoilState } from "recoil"; import { Industry, industryState } from "../atoms/industriesAtoms"; const manageIndustryData = () => { const [industryStateValue, setIndustryStateValue] ...

Issue with retrieving all phone numbers from a contact in Ionic

Hope you're doing well! I'm encountering an issue with Ionic Contacts. Currently, I'm able to retrieve all the contacts using my code but I need help extracting all the phone numbers associated with each contact. For example, if John has 3 ...

A single click is required for Observables to load on an HTML page

While working on my Angular web application, I encountered an issue with displaying data when using Observables and Subjects. Typically, when searching the Firebase DB, I use *ngFor="let myvar of _myvar | async" in my HTML to display the retrieve ...

Patience is key when waiting for one observable to respond before triggering another in Angular's async environment

What is my goal? I have several components with similar checks and data manipulation tasks. I am looking to centralize these tasks within an observable. To achieve this, I created an observable named "getData" in my service... The complexity lies in the f ...

Dynamically modifying the display format of the Angular Material 2 DatePicker

I am currently utilizing Angular 2 Material's DatePicker component here, and I am interested in dynamically setting the display format such as YYYY-MM-DD or DD-MM-YYYY, among others. While there is a method to globally extend this by overriding the " ...

The data type returned by a method is determined by the optional parameter specified in the

I have a situation where I need to create a class with a constructor: class Sample<T> { constructor(private item: T, private list?: T[]) {} } and now I want to add a method called some that should return: Promise<T> if the parameter list ...

Creating TypeScript models from a JSON response in React components

My Angular 2 application retrieves a JSON string, and I am looking to map its values to a model. According to my understanding, a TypeScript model file is used to assist in mapping an HTTP Get response to an object - in this case, a class named 'Custo ...

What is the best way to access JavaScript built-ins in Typings when faced with name conflicts?

I am currently in the process of updating the Paper.js Typings located on GitHub at this repository: github.com/clark-stevenson/paper.d.ts Within Paper.js, there exists a MouseEvent class, which is not an extension of JavaScript's MouseEvent, but ra ...

Angular 6: Harnessing the Power of RouterLinks

Can you navigate to a different section of another page using the defined ID without having to reload the entire page? ...