-
Notifications
You must be signed in to change notification settings - Fork 13.1k
fix: [Symbol.iterator]() lost on union with never
#62661
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
base: main
Are you sure you want to change the base?
fix: [Symbol.iterator]() lost on union with never
#62661
Conversation
|
@microsoft-github-policy-service agree |
|
@typescript-bot test it |
|
Hey @jakebailey, the results of running the DT tests are ready. Everything looks the same! |
|
@jakebailey Here are the results of running the user tests with tsc comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Everything looks good! |
|
@jakebailey Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@jakebailey Here are the results of running the top 400 repos with tsc comparing Everything looks good! |
|
@typescript-bot pack this |
|
Hey @RyanCavanaugh, I've packed this into an installable tgz. You can install it for testing by referencing it in your and then running There is also a playground for this build and an npm module you can use via |
|
This seems right. I can't construct anything that didn't error before but does now due to a circularity |
src/compiler/checker.ts
Outdated
|
|
||
| let allIterationTypes: IterationTypes[] | undefined; | ||
| for (const constituent of (type as UnionType).types) { | ||
| if (!!(getReducedType(constituent).flags & TypeFlags.Never)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
q: what if all union members reduce to never? wouldn't this break a case like this?
declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" });
const [el2] = o2; // errorThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, in that case TS allows the destructuring and types el2 as never.
I went with an alternative solution: reduce the whole iterable-like type instead of the union members: 93fb716 (#62661).
Added this case to the test as well
| @@ -0,0 +1,30 @@ | |||
| // @strict: true | |||
| // @noEmit: true | |||
| // @target: es5,esnext | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the es5 target should produce similar errors but right now it doesnt produce any
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not something that's related to this PR in particular, right? Lmk if you think this is something I can address from my end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel the issue is slightly more broad, it's about inconsistencies related to never and reduced nevers in unions etc. With that in mind, you have fixed up those inconsistencies for the es2015+ targets but they are still there for the es5 target. That's demonstrated by those error baseline differences and by this (that might overlap with the existing tests):
// @target: es5
declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" });
// ^? const o2: never
const [el3] = o2; // no error ???
declare const o3: never
// ^? const o3: never
const [el4] = o3; // Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.(2488)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symbol.iterator was not a part of ES5, it was introduced in ES2015. Indeed none of the cases in the new test file cause a type error with the ES5 target: Playground link.
I think addressing this issue is beyond the scope of this PR, but happy to discuss this further.
|
@typescript-bot test it |
|
Hey @jakebailey, I've packed this into an installable tgz. You can install it for testing by referencing it in your and then running There is also a playground for this build and an npm module you can use via |
|
Hey @jakebailey, the results of running the DT tests are ready. Everything looks the same! |
|
@jakebailey Here are the results of running the user tests with tsc comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Everything looks good! |
|
@jakebailey Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@jakebailey Here are the results of running the top 400 repos with tsc comparing Everything looks good! |
|
@Andarist I addressed your comment, let me know if you have any others |
Note that I only review here as an external contributor. I'm not a team member and I can't approve/reject PRs. |
src/compiler/checker.ts
Outdated
| */ | ||
| function getIterationTypesOfIterable(type: Type, use: IterationUse, errorNode: Node | undefined) { | ||
| if (type === silentNeverType) { | ||
| const reducedType = getReducedType(type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just type = getReducedType(type)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: a0a3bb4 (#62661)
Fixes #62462
A type's
[Symbol.iterator]()method is "lost" when union-ing that type with another type that's reducible tonever.The reason is that
getReducedTypewas not getting called bygetIterationTypesOfIterable, so non-iterable types that are reducible toneverwere not being erased out.