Reputation:
I would like a simple way to get a list of keys from an enumerator, I tried Object.keys, but it returned 6 keys, 0-5, I think it occours because when I tried foreach the enum, this returned keys and values list, is there a simple way to return only keys, I would not like to return to mount and return another list.
I will use this with react
My enum:
enum ObservationType {
Accomodation = 1,
Addtional = 2,
LandTransport = 3
}
Sample that I tried and returned six values:
{Object.keys(ObservationType).map((type) => <div>{type}</div>)}
Upvotes: 15
Views: 43732
Reputation: 276085
The ObservationType
object will have keys :Accomodation
, Additional
, LandTransport
, 1
, 2
, 3
and is fundamental to how enums work in TypeScript.
That said if you want just the string
names you can with a simple filter
:
{Object.keys(ObservationType)
.filter(k => typeof key === 'string')
.map((type) => <div>{type}</div>)}
Upvotes: 1
Reputation: 101
Try using
Object.keys(enumObj).filter(key => isNaN(Number(key)))
It covers all types of enums including Heterogeneous enums.
Upvotes: 10
Reputation: 917
The following can map the keys of the enum and you can use ObservationType[key] to get the value for each one as you go.
(Object.keys(ObservationType) as Array<keyof typeof ObservationType>).map(key, index) => {}
Upvotes: 0
Reputation: 9986
For string enums (with string values) you can just use Object.keys(myEnum)
/ Object.values(myEnum)
For numeric enums, the following methods works without isNan
, which can go wrong for certain keys:
/**
* Get the values for an enum that is numeric (has number values).
*/
export function enumValues(myEnum) {
return Object.values(myEnum).filter((o) => typeof o == 'number');
}
/**
* Get the keys for an enum that is numeric (has number values).
*/
export function enumKeys(myEnum) {
return Object.values(myEnum).filter((o) => typeof o == 'string');
}
Upvotes: 2
Reputation: 492
I had a hard time finding a good answer to this.
It looks like the enum
generates an Object
like this:
{
key0: 0,
key1: 1,
0: key0,
1: key1
}
So this is what I did:
const observationTypes: string[] = Object.keys(ObservationType).filter((_, i) => ObservationType[i] !== undefined).map((_, i) => ObservationType[i]);
This gives me an array of strings:
{
0: "a",
1: "b",
2: "c",
3: "d",
4: "e",
...
}
You could easily modify this to create a set of elements like in your question.
Upvotes: 2
Reputation: 2505
How about, Object.keys(ObservationType).filter(k => isNaN(Number(k)))
credit to @basarat whose answer I built on.
Upvotes: 2
Reputation: 442
Try using ts-enum-util
(github, npm):
import {$enum} from "ts-enum-util";
enum ObservationType {
Accomodation = 1,
Addtional = 2,
LandTransport = 3
}
// type: ObservationType[]
// value: [1, 2, 3]
const values = $enum(ObservationType).getValues();
// type: ("Accomodation" | "Addtional" | "LandTransport")[]
// value: ["Accomodation", "Addtional", "LandTransport"]
const keys = $enum(ObservationType).getKeys();
// directly map the enum value/key pairs
const valueDivs = $enum(ObservationType).map(
(value, key) => <div>{value}</div>
)
It takes care of ignoring the numeric key reverse lookup entries in the runt-time enum object for you, among other things.
Upvotes: 5
Reputation: 191779
From the TypeScript enum documentation:
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.
This means that if you're able, you may want to use string enums, e.g.:
enum ObservationType {
Accomodation = 'Acc',
Addtional = 'Addt',
LandTransport = 'LandT',
}
// Object.keys will only have the three keys.
Another way to handle this would be to keep track of the mapped values to get the reverse mappings only once. This requires the numeric keys of the object to be set first which is not necessarily a guarantee:
enum ObservationTypeNums {
Accomodation,
Addtional,
LandTransport,
}
Object.keys(ObservationTypeNums).reduce((arr, key) => {
if (!arr.includes(key)) {
arr.push(ObservationTypeNums[key]);
}
return arr;
}, []);
// arr now has only the string keys
Otherwise you will just have to filter out numeric keys in a way as you have done.
Upvotes: 5