Reputation: 2293
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
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
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
Reputation: 1048
// 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
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
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:
Another way: Retrieve enum key by value:
let enumKey = Object.keys(Colors)[Object.values(Colors).indexOf("BLUE COLOR")];
console.log(enumKey);
Output:
Test 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
Reputation: 11
I'd like to fix the code a little:
return Object.keys(myEnum).find(x => myEnum[x] === enumValue);
Upvotes: 1
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
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
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
Reputation: 3141
const findMe = Object.keys(Colors)[Object.values(Colors).indexOf("BLUE COLOR")];
https://jsfiddle.net/anniebbird/agy3unfk/3/
Upvotes: 56
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
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