-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow iterating through enum variants with for of #42457
Comments
This would create much larger output for enums, when it's just used by a few. And it would be kinda weird for flagged enums. Workarounds are trivial, for example with module merging. Or just with some small helper code: IMO enums generate the minimum amount of code needed for the functionality, and that's good. |
That requires duplicating the entire enum by hand. Obviously a bad solution (check the emoji responses to that comment!).
Yes I mentioned that code like this is currently the best option but it's a pretty bad option. This issue is about making something better.
This is your only valid point and the only real downside to this proposal, but I think the small increase in code size is worth it. |
Notes for people that might try to implement it (maybe me). I think there are two things to do to implement it.
|
There's an active TC39 proposal for enums (https://github.com/rbuckton/proposal-enum) so we would want to hold off on changing any runtime semantics of enums until that got through |
Thanks for the link. I got a bit carried away and had a go at implementing the iterator part of that proposal (same as mine but returns enum Test {
Foo,
Bar,
Baz,
}
for (const member of Test) {
const x: string = member[0];
const y: Test = member[1];
console.log(x, y);
}
const members: [string, Test][] = [...Test];
console.log(members); compiles with no errors to this Javascript var Test;
(function (Test) {
Test[Test["Foo"] = 0] = "Foo";
Test[Test["Bar"] = 1] = "Bar";
Test[Test["Baz"] = 2] = "Baz";
Test[Symbol.iterator] = function* () { yield ["Foo", 0]; yield ["Bar", 1]; yield ["Baz", 2]; };
})(Test || (Test = {}));
for (const member of Test) {
const x = member[0];
const y = member[1];
console.log(x, y);
}
const members = [...Test];
console.log(members); which produces this output
It might be better to use By the way editing these enormous files is a right pain - it absolutely rinses my laptop, and it makes it really hard to find stuff. All of the scrollbar annotations in VSCode are useless! Would be nice if they were just a little smaller. I'm sure you have had very long discussions about that!
I feel like it would be worth implementing just this part of the proposal now anyway, for the following reasons:
|
This remains uncommitted and we're not able to take a PR for it at this time.
|
There's a reasonable workaround for some situations that's worth noting:
|
Suggestion
π Search Terms
enum, iterate, variants
β Viability Checklist
My suggestion meets these guidelines:
Note that "is this a runtime feature?" doesn't really apply in this case since enums are already a runtime feature (maybe the only one?). This suggestion just modifies the compilation output slightly.
β Suggestion
The Typescript code for an enum...
...generates Javascript like this:
Unfortunately there's no nice way to iterate over the enum values. The prevailing suggestion on these two very highly upvoted StackOverflow questions is to use
for in
and then filter out the reverse mapping entries usingtypeof
. That sucks:string
ornumber
instead ofColour
.enum { Zero = 0, None = 0, ...}
, although I'm not 100% sure how duplicates should be handled anyway.I propose that the above enum code should compile to something like this:
This would allow you to write:
π Motivating Example / Use Cases
Probably the most common use is generating UI from enums (e.g. a colour drop-down), but this is very general purpose. The StackOverflow questions linked above demonstrate how much people want this. We've come across this twice already in our code - once for UI and once for collecting data per enum variant, e.g.:
Note there is a related but slightly different bug here: #39627 but it's more about how
for in
does unexpected things than about makingfor of
work. I don't think it really matters since you should never ever usefor in
anyway.The text was updated successfully, but these errors were encountered: