You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enums currently get outputted to an object with two-way mapping of numbers. This makes it hard to iterate through the names (or values) of an enum. A method on the enum object to get the keys of the enum would allow iterating.
See this StackOverflow question for a use case of iterating. (And use of a regular expression for filtering).
Possible Solutions:
Add a length property (for enums with default index)too limited
Function on enum type filtering keys looking for numbers (could break with other index types)
Add a function with the keys hard coded when compiling
I don't think this is a common enough case to emit such a helper for all enums that every TypeScript user writes.
Note that you can merge modules and enums to add methods to the enum yourself if you really do need this functionality. For example, using ES6 generators you can achieve something close to what you want:
It is a common case, for example, you may want to generate a dropdown list from enum dynamically. It is easy to implement too, just add length property to the enum.
Reacted by Daniel Caspers and Mahmood Dehghan Tazereh
Reacted by Filip Vestergaard, Alexander Trauzzi, Hunter Beast, Will, Martin Schneppenheim, Ezekiel Warren, Maciej Bukowski, Omer, alamothe, alberto-fp-24 and 28 more
Reacted by Jacob Kostenick, Vasil Dininski, alberto-fp-24, Thomas Wilgenbus, Dakota Jang, Kayleigh, Jeff Fairley, cah-sam, Steven, alamothe and 25 more
Reacted by Thomas Wilgenbus, cah-sam, Steven, Charlie Reitzel, Rodrigo Orem and 小猫
Well, generally how else are people able to show their support but by making some noise for the cause?
This issue is rank 4 on DuckDuckGo and 3 on Google when searching "typescript iterate enum" (which is how I got here as well). I guess wanting to iterate over enums is not an uncommon use case after all and both solutions that were brought up in here are essentially workarounds and quite bulky.
Reacted by Omer, harora-ot, Charlie Reitzel, rseeberg, TooManyDots, Rafael Araujo Lehmkuhl, Thunderforge, C. Davison, Kostiantyn Rudenko and fynulli
TypeScript isn't going to emit additional code for every enum just to enable you to do something you can already do by writing code in userland. All the data you need is present at runtime; there's no need for it.
Reacted by Anthony Ciccarello
Reacted by Charlie Reitzel, Andrey Sarafanov, Alex Yermakov, Alexis Bertholom, Connor Low, David Kuťák, C. Davison, Kostiantyn Rudenko, John Binning, fynulli and 1 more
I guess by going down that thought we should all be writing and compiling our own assembly code since everything is technically already possible there? /j
I think asking "Can it work without the new feature?" is the wrong approach. The main purpose of a programming language is to make it easy for people to produce solutions. If this new feature accomplishes this, is intuitive (Because let's face it: Both solutions are not unless you are knee deep in the specs) and comes at a reasonable cost: Why not?
There are many examples of "sugar" in JS, basically the whole Array methods are. So forgive me for asking but why is it such a big deal for TS to add aditional functionality? I'm guessing the third part of my before mentioned feature requirements is the problem?
Reacted by Rafael Araujo Lehmkuhl, ClxZero, Kostiantyn Rudenko and fynulli
I want to add one more technical point. One suggested approach is http://stackoverflow.com/a/18112474/1704166. The problem with it is that it doesn't iterate over values in a type-safe manner - it will produce numbers or strings. So downstream of iteration type safety is lost.
I believe a lot of people who need the iteration are lead to that approach and that's bad. Dan Quirk (@danquirk)'s solution is fine and I want to give credit to it.
As for philosophical debate, I think a lot of people who are coming to Typescript from other languages, while in awe of other language features, are left wondering about enum support. Enums in Typescript are not on par with other high-level languages. Personally I don't care what it is compiled down into, as long as it behaves like I expect from an enum type. Maybe it should be reassessed if the right compromise was made between enum usefulness and complexity of the generated code.
Reacted by Florian Albrecht, xuiqzy, despian, LievenLuyckxCegeka, BinHong Lee, Charlie Reitzel, Laurent Pellegrino, rseeberg, Orlando Parisblue, Saucistophe and 7 more
It is an evil hack. But it does work generically. I tested it with a numeric/integral enum.
Note: it does not compile in JSFiddle, which does not recognize the keyof operator. But it works with current Typescript in my Angular 8 code and Jasmine unit test. Hth.
To me, there is nothing philosophical about current support for enum iteration in Typescript. It is just broken. It doubles the number enum values, present each one twice: once for the name, and again for the value. There's no clear cut way to distinguish between names and values. Nor any guarantee of order in the language (could break with any TS update). There's no philosophy there to defend. Just a misunderstanding of what enumerated types mean in any scripting language (e.g. Java, Python, ...).
A practical issue I am having is how to deserialize values from the server (via JSON) into actual enum values in my Typescript code. Some evil hack may work yet. But it really should be easy to iterate through enum instances, compare the given value to either the name or value and, if I have a match, use the current enum instance. Currently, this direct approach is not possible.
enum Planet {
MARS(1),
VENUS(2),
EARTH(3),
MARS(4), ...
NEPTUNE(8);
int pno;
Planet( int pno ) {
this.pno = pno;
}
public static Planet findPlanetByNumber( int planetNum ) {
for (Planet p : Planet.values()) {
if ( planetNum == p.pno ) {
return p;
}
}
return null;
}
}
classQueue{privatereadonlyeventEmitter: EventEmitter=newEventEmitter();// some linked list implementation hereon(event: QueueEvents,listener: (...args: any[])=>void){this.eventEmitter.on(event,listener);}}
Now let's iterate the QueueEvents (in some unit test):
Doesn't work since members of the array are strings or numbers here, not enums. For example, you can't pass them to a function expecting an array of enum values.
Is there a reason not to use the enumerable property attribute?
It could only allow the keys of the enum to appear during a for loop or with Object.keys, and hiding the values.
While keeping the forth and back translation between keys and values, as is already the case.
Building upon the previous solutions, I came up with something along the lines of the following code. for numeric enum only
I figured I might as well share what I did in order to iterate over enums.
This is probably not the most efficient or elegant way to do this, but it yields values with the correct type, works with both numeric and string enums, is pretty short/straightforward and works for me:
functionenumValues<Textendsstring>(enumObj: {[key: string]: T}): IterableIterator<T>;functionenumValues<Textendsstring|number>(enumObj: {[key: string]: T}): IterableIterator<Exclude<T,string>>;function*enumValues<T>(enumObj: {[key: string]: T}): IterableIterator<T>{letisStringEnum=true;for(constpropertyinenumObj){if(typeofenumObj[property]==='number'){isStringEnum=false;break;}}for(constpropertyinenumObj){if(isStringEnum||typeofenumObj[property]==='number'){yieldenumObj[property];}}}// use like this; string enums should work tooenumMyEnum{foo,bar,baz}for(constvalueofenumValues(MyEnum)){console.info(value);// value is of type MyEnum}
Reacted by Norman Breau, Robert Kroll, imckl, 小猫, 0xthk, Rafael Araujo Lehmkuhl, Josh Grift, alamothe, Jared Henderson, Miciah Henderson and 3 more
Activity
danquirk commentedon Sep 11, 2015
I don't think this is a common enough case to emit such a helper for all enums that every TypeScript user writes.
Note that you can merge modules and enums to add methods to the enum yourself if you really do need this functionality. For example, using ES6 generators you can achieve something close to what you want:
aciccarello commentedon Sep 14, 2015
Okay, thanks for the suggestion. I'll see if that is a suitable solution.
Novalaina commentedon Jan 3, 2016
Seems like it would be a common use-case to me. I certainly would like that included automatically.
bladepan commentedon Feb 23, 2016
It is a common case, for example, you may want to generate a dropdown list from enum dynamically. It is easy to implement too, just add length property to the enum.
npiv commentedon May 19, 2016
I don't understand the argumentation to not include this at all. Too complex maybe, but not a common use case...
What other language has enums and no way to iterate over them?
RyanCavanaugh commentedon May 19, 2016
You can iterate over them. See http://stackoverflow.com/a/18112474/1704166 .
npiv commentedon May 21, 2016
Ryan Cavanaugh (@RyanCavanaugh)
Thank you that does work. My mistake - I misunderstood this issue.
alamothe commentedon May 3, 2018
Dan Quirk (@danquirk) Can't compiler just emit the same code?
It is really sad it's not supported, as every other language with enums have the functionality
omerman commentedon Jun 6, 2018
Dan Quirk (@danquirk) I agree with alamothe so much that I'm leaving this comment saying just that.
RyanCavanaugh commentedon Jun 6, 2018
Please don't show up with noise comments.
saenglert commentedon Nov 26, 2018
Well, generally how else are people able to show their support but by making some noise for the cause?
This issue is rank 4 on DuckDuckGo and 3 on Google when searching "typescript iterate enum" (which is how I got here as well). I guess wanting to iterate over enums is not an uncommon use case after all and both solutions that were brought up in here are essentially workarounds and quite bulky.
RyanCavanaugh commentedon Nov 26, 2018
TypeScript isn't going to emit additional code for every enum just to enable you to do something you can already do by writing code in userland. All the data you need is present at runtime; there's no need for it.
saenglert commentedon Nov 26, 2018
I guess by going down that thought we should all be writing and compiling our own assembly code since everything is technically already possible there? /j
I think asking "Can it work without the new feature?" is the wrong approach. The main purpose of a programming language is to make it easy for people to produce solutions. If this new feature accomplishes this, is intuitive (Because let's face it: Both solutions are not unless you are knee deep in the specs) and comes at a reasonable cost: Why not?
There are many examples of "sugar" in JS, basically the whole Array methods are. So forgive me for asking but why is it such a big deal for TS to add aditional functionality? I'm guessing the third part of my before mentioned feature requirements is the problem?
alamothe commentedon Nov 26, 2018
I want to add one more technical point. One suggested approach is http://stackoverflow.com/a/18112474/1704166. The problem with it is that it doesn't iterate over values in a type-safe manner - it will produce numbers or strings. So downstream of iteration type safety is lost.
I believe a lot of people who need the iteration are lead to that approach and that's bad. Dan Quirk (@danquirk)'s solution is fine and I want to give credit to it.
As for philosophical debate, I think a lot of people who are coming to Typescript from other languages, while in awe of other language features, are left wondering about enum support. Enums in Typescript are not on par with other high-level languages. Personally I don't care what it is compiled down into, as long as it behaves like I expect from an enum type. Maybe it should be reassessed if the right compromise was made between enum usefulness and complexity of the generated code.
CharlieReitzel commentedon Oct 11, 2019
Edit: This solution works for my use case:
https://stackoverflow.com/questions/52370544/parse-string-as-typescript-enum
It is an evil hack. But it does work generically. I tested it with a numeric/integral enum.
Note: it does not compile in JSFiddle, which does not recognize the
keyofoperator. But it works with current Typescript in my Angular 8 code and Jasmine unit test. Hth.For easy and useful approaches, that haven't managed to bog down runtimes, have a look at Java: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html. Or Python: https://docs.python.org/3/library/enum.html.
To me, there is nothing philosophical about current support for enum iteration in Typescript. It is just broken. It doubles the number enum values, present each one twice: once for the name, and again for the value. There's no clear cut way to distinguish between names and values. Nor any guarantee of order in the language (could break with any TS update). There's no philosophy there to defend. Just a misunderstanding of what enumerated types mean in any scripting language (e.g. Java, Python, ...).
A practical issue I am having is how to deserialize values from the server (via JSON) into actual enum values in my Typescript code. Some evil hack may work yet. But it really should be easy to iterate through enum instances, compare the given value to either the name or value and, if I have a match, use the current enum instance. Currently, this direct approach is not possible.
newlukai commentedon Oct 24, 2019
Not so common use case (?):
Now let's iterate the QueueEvents (in some unit test):
Doesn't work since
eventis astringhere, not aQueueEvents.xiaoxiangmoe commentedon Nov 29, 2019
example here:
CharlieReitzel commentedon Nov 29, 2019
Doesn't work since members of the array are strings or numbers here, not enums. For example, you can't pass them to a function expecting an array of enum values.
For something that does work, see:
https://stackoverflow.com/questions/52370544/parse-string-as-typescript-enum.
xiaoxiangmoe commentedon Nov 30, 2019
Update:
houfeng0923 commentedon Jan 9, 2020
can enum with number values compile like this :
i have a babel plugin test it babel-plugin-iterable-enum
CharlieReitzel commentedon Jan 10, 2020
houfeng (@houfeng0923) I like the looks of that. Nice idea pushing the reverse mapping into the
__proto__space.etnbrd commentedon Jan 28, 2020
Is there a reason not to use the
enumerableproperty attribute?It could only allow the keys of the
enumto appear during aforloop or withObject.keys, and hiding the values.While keeping the forth and back translation between keys and values, as is already the case.
Building upon the previous solutions, I came up with something along the lines of the following code.
for numeric
enumonlyTicmea commentedon Sep 17, 2020
I figured I might as well share what I did in order to iterate over enums.
This is probably not the most efficient or elegant way to do this, but it yields values with the correct type, works with both numeric and string enums, is pretty short/straightforward and works for me: