-
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
Make enum indexes non-enumerable #53973
Comments
(Note: I'm not a TS team member, so I do not speak authoritatively) #4753 was already declined, and this is just asking for the same thing in a different way, except more intrusively because it breaks existing behavior. I'd love to go back in time to change enums, but in this timeline I think we're probably stuck with this. If you want to iterate through the forward mappings only you can suppress numeric-like keys yourself: enum E { A, B }
console.log(Object.keys(E).filter(k => "" + (+k) !== k)); // "A", "B" (which works, ignoring weirdnesses like #48956). No, it's not ergonomic, but at least you don't have to wait for TypeScript enums to change. |
@jcalz #4753 suggests more complicated solution because additional field should be used - [Symbol.iterator]. So it was the reason to decline it. You can check it here:
Also,
But what’s the reason? TS 5.0 already broke current enum behaviour (UPD: see 50528) and it’s not the first time (also - this, this). Do you see some limiting design decisions that block my suggestion? If so, can you share your thoughts?
I strongly disagree with this point because developers listen the “community voice” and don’t use the feature at all - you can check links I provided before. So it leads to more complicated solutions with custom enum implementations; also export const LoginMode = {
device: 'device',
email: 'email',
social: 'social',
} as const;
export type LoginMode = keyof typeof LoginMode; (Thanks @basarat for provided example) UPD. Yes, it works, but it’s not enough semantical; it has drawbacks similar to using I think better to use single solution for real dev cases instead of keeping current non-ergonomic behaviour. |
How would making enum objects iterable break people? Do people depend on enum objects not being iterable?
This solution is also more complicated because it
I assume that since enumerable reverse mappings in enum objects have been around for quite a while there might well be real world code that enumerates them. But I don't have any concrete statistics here so maybe it's an acceptable break? 🤷♂️ I expect that the TS team will decline this, but I'm just a community member that expects reverse mappings to be present in the key list, and I don't intend to speak on behalf of others, so I'll stop speculating and let them give reasons if they do decline it.
Cross-referencing to #50528.
Unfortunately I think that expression-level TypeScript features that don't exist in JavaScript should probably be avoided where possible, including enums (and parameter properties, and I guess I'll stop interacting now to let you and others discuss if you want. Good luck! |
Some thoughts for other community members:
The short answer is “no” but I prefer to not guess it because technically adding the new “system” field is breaking change. For example, someone can write lodash-like helper that returns the last element of collection if iterable and returns last indexed value otherwise. We don’t know what people expect for this enum:
I mean “complicated in runtime” when some helpers should be added to prototype chain in case of [Symbol.iterator]
Reverse mapping & enumeration are not related; idk who wanna to depend on index enumeration but technically it’s a breaking change. I pointed earlier that I prefer to not speculate what breaking change is.
When some functionality already exists and it’s not private then someone will be use it. If enums are bad why not remove it completely (with deprecation step)? Also, enums behaviour is not “frozen” because some breaking changes were added earlier (see previous comment). Keeping non-ergonomic behaviour is OK only for JS (“don’t break the web”). Namespaces are also not bad-by-default just because JS already has modules. Namespace functionality OK and maybe preferred for some real-world cases (I know at least 2 cases but I don’t wanna to discuss it here). |
P.S. A good example that TS enums behaviour was changed for better ergonomic is my old issue: My suggestion was applied in TS 5.0 😉 |
I don't think this change alone meaningfully moves the needle on whether you should want to use Breaking a ton of working code (I assure you it exists) to change not-wrong behavior that's been shipping for 10 years just isn't a good trade-off. |
@RyanCavanaugh
Issues with “unstable” enum indexes and nominal typing I don’t consider as a problem because it’s how enum works in other languages - the enum idea is to provide stable keys, not values - because enums allow a developer to define a set of named constants. With best regards to @basarat nevertheless I don't know why he has a different opinion with considering So, following the great work that was done for enums unification (release 5.0, special thanks to you, @ahejlsberg and @sandersn for working with the PR), some additional changes can be made & it will cover 80-90% problem cases. You are welcome to close the issue or leave it for other opinions |
This issue has been marked as "Declined" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Suggestion
For now TS numeric enums are compiled with indexes so the result can be confusing at runtime:
The behaviour is unusual so many community members just suggest not use enums at all. It’s the key point because some really useful language feature became “forbidden” because no one understands how to use it correctly:
TypeScript Enums are Terrible. Here's Why
Why TypeScript enums suck
TypeScript Enums are Bad // Alternatives to use
My idea (not only my - see) is to use
enumerable: false
for indexes.UPD. Some steps for string & numeric enums unification were already made for TS 5.0; the whole part of roadmap concerned the unification:
Unification Between Numeric and Literal enums
@ahejlsberg wrote some meaningful things:
🔍 Search Terms
enums, enumerable, iteration
✅ Viability Checklist
My suggestion meets these guidelines:
Other related issues:
#4753 (Suggestion: Iterate through Enum values)
#2457 (Allow iterating through enum variants with for of)
#51150
#48193 (see the comment)
The text was updated successfully, but these errors were encountered: