-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Typescript incorrectly resolves discriminated unions of indexed types #37052
Comments
Haven't checked if this is a duplicate yet but whatever the issue is doesn't seem to have to do with discriminated unions (or even necessarily unions) or indexed access either per se: type Foo = {
"a": unknown
"b": string;
}
type Bar<T extends keyof Foo> = {
type: Foo[T];
}
const err: Bar<"a"> = null! as Bar<"b">; // error
// Bar<"b"> is not assignable to Bar<"a">
const okay: { type: Foo["a"] } = null! as { type: Foo["b"] }; |
Not sure why we're not falling back to structural comparison here. Workaround
|
I believe the issue here is that we measure indexed access types such as |
@weswigham Don't recall if you've experimented with this before. |
|
It's also worth mentioning that the compiler behavior changed at some point. The code in the playground example compiles in TS 3.3.3, but not in TS 3.5.1. (Also, thanks for the workaround, @RyanCavanaugh!) |
@weswigham I does seem that when a type variable is used as the index type in an indexed access type, its variance effectively becomes unmeasurable (because a relation between property names implies nothing about a relation between the types of those properties). |
I've found a simpler workaround that doesn't involve conditional types: the type indexing must occur external to the definition of the object's shape. As an example, here's a slight modification to fix @jcalz 's example: type Foo = {
"a": unknown
"b": string;
}
type BarInner<T> = { type: T };
type Bar<T extends keyof Foo> = BarInner<Foo[T]>;
const err: Bar<"a"> = null! as Bar<"b">; // no longer an error! |
I'm closing this as a design limitation. The core issue is that we conservatively measure most indexed access types as invariant, where structural comparisons might be less restrictive. For example, see my comment here. |
TypeScript Version: 3.8-Beta
Search Terms: discriminated unions indexed types
Expected behavior:
b1
should be assignable toa1
Actual behavior:
The following error
Type '"B"' is not assignable to type '"A"'
Code
Output
Compiler Options
Playground Link: Provided
The text was updated successfully, but these errors were encountered: