MAK
MAK

Reputation: 2293

How to get enum key by value in Typescript?

I have an enum like this:

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

Could you let me know how to get enum key by value please? i.e., I need to pass "BLUE COLOR" and get 'BLUE'.

Colors["BLUE COLOR"] gives error 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'.

Upvotes: 113

Views: 192685

Answers (12)

DANser
DANser

Reputation: 37

Don't, how can you access <key> by <value> if two different keys have identical <value>? Are you sure typescript guarantees values to be unique? Just adds more undefined behaviour.

Upvotes: 0

I.sh.
I.sh.

Reputation: 2148

Here's a way to get enum key by it's value, while passing any enum and any of it's values as a variable:

// Create your own Enum type
type Enum = { [id: number]: string | number };

const getEnumKeyByValue = <T extends Enum>(
  myEnum: T,
  enumValue: string | number
): string => {
  for (const key in myEnum) {
    if (myEnum[key] === enumValue) return key;
  }

  throw new Error(`No key matches the value: '${enumValue}' in given enum.`);
};

Usage:

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

const value = "RED COLOR"
const key = getEnumKeyByValue(Colors, value);

Upvotes: 0

kheengz
kheengz

Reputation: 1048

Using Bracket Notation to access Value by Key (where key is a varaible)

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


// Access Enum using bracket notation
let key: keyof typeof Colors = "BLUE";
let value = Colors[key];

console.log(value);

Upvotes: 0

JC Martin
JC Martin

Reputation: 81

Everyone else is sharing runtime solutions, but if you want a Typescript solution here it is:

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']]

First create a type that swaps the places of the enum's keys and values. (ReverseEnum)

By using typeof enum it allows you to do indexed access into the enum's keys as a string. Then you get the name of that key using the reversed enum type.

It works perfectly with autocomplete on the value string and everything.

Upvotes: 1

Md Farid Uddin Kiron
Md Farid Uddin Kiron

Reputation: 22523

If you want to get your enum key by value in that case you have to rewrite your enum in following manners: But same format also might be work in older version as well.

For Vanilla Js it should be like below:

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

For .tsx it should be like below:

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

For .ts it should be like below:

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

Then you can get like this way:

Retrieve enum key by value:

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

Output:

enter image description here

Another way: Retrieve enum key by value:

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

console.log(enumKey);

Output:

enter image description here

Test on jsfiddle:

Coding sample on jsfiddle

Note: There are new annoucement published on 25th August with TypeScript 4.8. Please be aware of it. You could have a look here.

Upvotes: 85

Michael Fyodorov
Michael Fyodorov

Reputation: 11

I'd like to fix the code a little:

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

Upvotes: 1

josue.0
josue.0

Reputation: 843

Improved getEnumKeyByEnumValue by adding type checks:

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/

Upvotes: 4

nikiphoros
nikiphoros

Reputation: 148

try like this

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

Upvotes: 8

Nazarii Repak
Nazarii Repak

Reputation: 201

Improved getEnumKeyByEnumValue without using any:

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

Upvotes: 20

Anna
Anna

Reputation: 3141

const findMe = Object.keys(Colors)[Object.values(Colors).indexOf("BLUE COLOR")];

https://jsfiddle.net/anniebbird/agy3unfk/3/

Upvotes: 56

Nux
Nux

Reputation: 7098

I am using this 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] : '';
}

Tests with 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');
  });
});

Hope it helps someone

Upvotes: 27

Emanuele Scarabattoli
Emanuele Scarabattoli

Reputation: 4489

You can do something like this fetching the enum keys:

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

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

Upvotes: 1

Related Questions