You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
3.5 Breaks function assignments that use a complex Discriminated Unions Type #31833
Search Terms: Discriminated Unions Type, Function, Assignment, Type Property
Code
typeFoo1={type: 'foo1';extra: number;};typeFoo2={type: 'foo2';extra: string;};typeBoth=Foo1|Foo2;typeFooTypes=Both['type'];exporttypeFooFromType<TextendsFooTypes,OextendsBoth=Both>=Oextends{type: T} ? O : never;typeFooExtraFromType<TextendsFooTypes>=FooFromType<T>['extra'];functionfnWithFooExtra<TextendsFooTypes>(type: T,extra: FooExtraFromType<T>){}// changing this to typeof fnWithFooExtra fixes it, even though it produces the exact signaturetypeFnType=<TextendsFooTypes>(type: T,extra: FooExtraFromType<T>)=>void;// The error is produced here:constfn: FnType=fnWithFooExtra;
Worked for a long time, but 3.5.1 breaks it. it hasn't been fixed on next. I tried 3.6.0-dev.20190608.
Interestingly, it breaks only on extra and not on the type itself. meaning that if I change FooExtraFromType to FooFromType it works.
If I use typeof instead of writing the signature it works. this is really weird as they are the exact same signature.
Expected behavior:
Compile as it had been working up to 3.4.5.
Actual behavior:
'fn' is declared but its value is never read.ts(6133)
Type '<T extends "foo1" | "foo2">(type: T, extra: (FooFromType<T, Foo1> | FooFromType<T, Foo2>)["extra"]) => void' is not assignable to type 'FnType'.
Types of parameters 'extra' and 'extra' are incompatible.
Type 'FooFromType<T, Foo1>["extra"] | FooFromType<T, Foo2>["extra"]' is not assignable to type 'FooFromType<T, Foo1>["extra"] & FooFromType<T, Foo2>["extra"]'.
Type 'FooFromType<T, Foo1>["extra"]' is not assignable to type 'FooFromType<T, Foo1>["extra"] & FooFromType<T, Foo2>["extra"]'.
Type 'number' is not assignable to type 'FooFromType<T, Foo1>["extra"] & FooFromType<T, Foo2>["extra"]'.
Type 'number' is not assignable to type 'FooFromType<T, Foo2>["extra"]'.
Type 'number' is not assignable to type 'string'.
Type 'FooFromType<T, Foo1>["extra"]' is not assignable to type 'FooFromType<T, Foo2>["extra"]'.
Type 'FooFromType<T, Foo1>' is not assignable to type 'FooFromType<T, Foo2>'.
Type 'FooFromType<T, Foo1>["extra"]' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.ts(2322)
Playground Link: Doesn't break on playground, I guess the version is old.
// You need the two aliases to avoid variance measurements.typeA1=<Textends{x: number,y: string}|{x: boolean,y: number}>(x: T["x"|"y"])=>voidtypeA2=<Textends{x: number,y: string}|{x: boolean,y: number}>(x: T["x"|"y"])=>voiddeclareconsta: A1;letb: A2=a;// error, even though A1 and A2 are identical.
Another interesting case:
typeObj={x: number,y: string}|{x: boolean,y: number};functionfun<TextendsObj>(l: {x: T["x"|"y"]},r: {x: T["x"|"y"]}){l=r;// was ok, now error}
Activity
fatcerberus commentedon Jun 9, 2019
Working Playground link
Indexed access type + contravariance + inferred intersection = #30769, I'd wager.
jack-williams commentedon Jun 9, 2019
Fix up: #31837
jack-williams commentedon Jun 9, 2019
Here is a smaller repro.
Another interesting case:
jcalz commentedon Feb 21, 2021
oof, just bonked into this with code like
in this SO question
RyanCavanaugh commentedon Mar 5, 2024
No longer errors, though jcalz's still does.