-
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
Improve soundness of indexed access types #30769
Conversation
Has the behaviour that was added in #27490 been taken out? The following function did error, but not under the new rules. function fun<U extends { a: T }, T, K extends 'a'>(u: U, k: K, shambles: T): U[K] {
u[k] = shambles; // was error
return u[k];
}
const result: number = fun<{ a: number }, unknown, 'a'>({ a: 42 }, 'a', 'a string'); I think the reason that the test-cases from #27470 didn't regress is because the restrictive instantiation has been subsequently added to conditional types, which catches the error too. |
Yes, but that behavior wasn't right. For an indexed access The real (and orthogonal) issue in your example is that we treat an assignment to What has changed with this PR is that for a It's all rather involved! |
@weswigham Can you take a look at why this is failing on |
Looks like we're pulling out some unexpected index signatures from the target or something? The bug should repro in the test harness, will just need to copy the relevant types into a test file. |
@weswigham It's actually identifying an unsafe coercion. It used to be that The easy fix is to explicitly cast the array parameter to |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at e1fd5e5. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the Definitely Typed test suite on this PR at e1fd5e5. You can monitor the build here. It should now contribute to this PR's status checks. |
Thanks for the detailed write-up @ahejlsberg.
True, though did you not add behaviour to prevent pulling down |
With latest commits there are three RWC projects with new errors. The errors in two of the projects are minor and identify unsoundness that we previously didn't catch. The last project, |
@typescript-bot test this |
@ahejlsberg If "a type argument for |
An indexed access |
Could the errors in this test case be overly strict?
This
Shouldn't TypeScript assume the user is reading the function parameters and trust them not to call Conversely, the user may have a special need for writing a writable any typed function like |
With this PR we improve soundness of indexed access types in a number of ways:
T[K]
occurs on the source side of a type relationship, it resolves to a union type of the properties selected byT[K]
, but when it occurs on the target side of a type relationship, it now resolves to an intersection type of the properties selected byT[K]
. Previously, the target side would resolve to a union type as well, which is unsound.T
with a constraintC
, when an indexed accessT[K]
occurs on the target side of a type relationship, index signatures inC
are now ignored. This is because a type argument forT
isn't actually required to have an index signature, it is just required to have properties with matching types.{ [key: string]: number }
is no longer related to a mapped type{ [P in K]: number }
, whereK
is a type variable. This is consistent with a string index signature in the source not matching actual properties in the target.T
andK extends 'a' | 'b'
, the types{ a: T, b: T }[K]
andT
are now considered related where previously they weren't.Some examples:
Previously, none of the above errors were reported.
Fixes #27895.
Fixes #30603.