-
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
Object.values(Enum) should return an array of Enum's value's type #33200
Comments
The error looks reasonable to me. Why are you checking for Maybe you're not aware that the type named |
Our real-world use case here is that the input to
Perhaps more importantly, prior to 3.6.2, this functionality worked exactly as expected. It was the (supposedly non-breaking, were semver followed) update that broke this purely at build time. |
Here's the relevant type definitions for interface ObjectConstructor {
values<T>(o: { [s: string]: T } | ArrayLike<T>): T[]; // first overload
values(o: {}): any[]; // second overload
} In TS3.5 and below, But TS3.6 included #31687, allowing enum objects to be seen as implicitly having index signatures. So, starting in TS3.6, That means in TS3.5 the compiler happily allowed you to call Starting in TS3.6, you are now forced to deal with the fact that The short answer here is you should probably widen |
I really don't think what we are asking for is particularly complex or confusing. At runtime,
This is certainly disappointing, and it is nice to see an attempt to tighten things up a bit. But unfortunately they have not been tightened up correctly.
No, we want We would also like it if breaking changes were not made in a minor version update. If this breaking change is absolutely necessary, it should be made with TypeScript version 4.x, not in a minor version update. It's very notable that according to Dependabot, this version update saw an over 10% failure rate, despite being a minor update, when most other builds have less than 3%. Heck, even the 2.9.2 → 3.0.1 breaking change had a lower rate of failure than this one! Surely Microsoft can not consider that acceptable. |
Except that's exactly what enum Role {
Admin = 'ADMIN',
Results = 'RESULTS',
Finish = 'FINISH',
Config = 'CONFIG'
}
declare let x: Role;
let y: 'ADMIN' | 'RESULTS' | 'FINISH' | 'CONFIG' = x; // ok You wouldn't argue that if you had an array of type tl;dr: TS knows statically at compile time the exact string values contained in |
For better or worse, TS doesn't do semantic versioning; see #31761 |
To reiterate: this all seems to be working as intended. You should change your code to something like enum Role {
Admin = 'ADMIN',
Results = 'RESULTS',
Finish = 'FINISH',
Config = 'CONFIG'
}
const allRoles: string[] = Object.values(Role); // this is what I want, compiler!
allRoles.forEach(role => { console.log(typeof role); });
allRoles.includes('hello'); which communicates your intent to the compiler ( |
The original PR suggests a workaround: Since numeric enums use older, looser rules than string enums, you can get close to the old behaviour by adding an entry to However, anytime something comes from user input, you should expect to assert or narrow its type before the compiler understands it. That code will necessarily involve some bending of the type system since the checks are runtime, but the errors you're getting are at compile-time. For 3.6, your checks that strings from user input are actually members of an enum now need associated assertions to make the type system leave you alone until the check is done. I would personally write it as Object.values(Role).includes('hello' as Role) |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
2 similar comments
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Array's `include` function checks whether or not the `searchElement` exists in it, and returns the appropriate boolean value as an answer. However, in the current implementation, TypeScript is requesting the type of `searchElement` to be a member of the array, instead of receiving any value as `searchElement`. This in turn forces the user to know in advance whether or not the `searchElement` is a member of the array, which defeats the whole purpose of using the 'include' function. The way users currently workaround that problem is by overriding the TypeScript mechanism by using "as", as suggested by @sandersn in here: microsoft#33200 (comment) . See also https://stackoverflow.com/questions/43804805/check-if-value-exists-in-enum-in-typescript . I believe that the purpose of the `include` function is to allow any variable, even if its type is unknown, to be searched in the array and get a boolean answer, and therefore I suggest the following changes. Playground: https://www.typescriptlang.org/play?#code/LAKApgdgrgtgBAMQEoFUCSAVAynA3qOOAQQAUSAZAUTgF44ByAQ3oBoC4AhIgOR6NoYAjVqAC+oUADMoEAMYAXAJYB7CHEUBnAGqMANooAmWKAAcTygE7ywBhBaiL5ACigawFtBBNR5ALjgyANYQygDuEACU-oLKyrpgjGr4IIQA9ABUEilwGAAWYHCScbphihAA5nD6EAWacPL5cBpQ5eVgGtYGcKGMAJ71yt2WgYwWyjJdjixwiZPyQxaBGtOCPt25-QaDaHC5jABuBfKDyocWFoYFGL0mYFiyFybyAPzsAOobcFtwO3uHAzMNG4rPU9vMGgVXO5PN55nVkOhsNNQrlFPEfvR4CF5s0LLV5ni9Lp+nUnLNQYx5PQNKCCii4gVvBZzG44MpJAENGVKgADMqyXRQAxgHkRV4gdiEPHyKAWNQAeUEACswAoAHT7PRQdpOBGYLARNX8wXCjQuYEwtaMGl67ARADckrg7HSqXY0tlCuVqvkGq1OttBqNchNOqhHi8PgdcFSqRyuTGoRpiTg7jGFn8RAs5VgkHm7PqNwK9CCIXC9HUNOxgK55QgjEE6OOcBMo0YMDA1gsbI58iLDED9DVOX7JYgwTCEArdWr1tr9cbR0GfduA9Q+rVXF4vCHTgATABmAAsAFYImIsrJVBoGWqSuUnJodPojKZzFYbHYHM5A2rSBRKAiaNYzgSgAA9bgUGx-HkewwFAK8IBveI72UB8nz0QxjDMSxOi-RwnHoYQgPtGM43AyDOhguCEOvW970fbRMNfHCP1sewCPoWR6BIsjQIgn1oMKPQ3FopD6LQxjnywt9cM-DjnGgXRdF4kCKMEgx-EkET4JARDkLAVD0KYl9sPfPCFKcXBRFU8iBKgzThN0NwgA
Search Terms: Object.values
Code
Expected behavior:
Object.values(EnumType)
at build time should be returning an array of the same type as the values of theEnumType
.Actual behavior:
Object.values(EnumType).includes('enumValueType')
errors out withIt appears as though, at build time,
Object.values(EnumType)
is parsed as returning an array ofEnumType
s.Error first encountered on Typescript
3.6.2
. Still present as oftypescript@next
.Playground Link: Playground link. Playground does not appear to be correctly using ES2017 and Typescript 3.6.2/3.7.0 are not available.
The text was updated successfully, but these errors were encountered: