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
Polymorphism doesn't work with mapped type args and strictFunctionTypes #27984
interfaceBase<P>{method: (args: Readonly<P>)=>void;}functionfn(arg: Base<any>){}// It worksfn({}asBase<{foo: string}>)// Why error?interfaceChild<P>extendsBase<P>{}fn({}asChild<{foo: string}>)
Expected behavior:
No error
Actual behavior:
Error:
Argument of type 'Child<{ foo: string; }>' is not assignable to parameter of type 'Base<any>'.
Types of property 'method' are incompatible.
Type '(args: Readonly<{ foo: string; }>) => void' is not assignable to type '(args: Readonly<any>) => void'.
Types of parameters 'args' and 'args' are incompatible.
Type 'Readonly<any>' is not assignable to type 'Readonly<{ foo: string; }>'.
Property 'foo' is missing in type 'Readonly<any>'.
changed the title [-]Polymorphism doesn't work with Readonly args and strictFunctionTypes[/-][+]Polymorphism doesn't work with mapped type args and strictFunctionTypes[/+]on Oct 19, 2018
The root cause of the issue seems to be that for Base<T>, since it's an interface we type, we see that it matches with Base<{ foo: string }> and measure the variance of each type parameter and perform comparisons accordingly, while for Child<T>, despite it being identical to Base<T>, since it is a different reference, we do not do variance measurements, and instead fall back to structural comparisons, which fail (due to how any works and the type having a contravariant position).
Activity
diegohaz commentedon Oct 19, 2018
Actually, it errors for any mapped type:
https://www.typescriptlang.org/play/index.html#src=interface%20Base%3CP%3E%20%7B%0D%0A%20%20%20%20method%3A%20(args%3A%20%7B%20%5BK%20in%20keyof%20P%5D%3A%20P%5BK%5D%20%7D)%20%3D%3E%20void%3B%0D%0A%7D%0D%0A%0D%0Afunction%20fn(arg%3A%20Base%3Cany%3E)%20%7B%20%7D%0D%0A%0D%0A%2F%2F%20It%20works%0D%0Afn(%7B%7D%20as%20Base%3C%7B%20foo%3A%20string%20%7D%3E)%0D%0A%0D%0A%2F%2F%20Why%20error%3F%0D%0Ainterface%20Child%3CP%3E%20extends%20Base%3CP%3E%20%7B%20%7D%0D%0Afn(%7B%7D%20as%20Child%3C%7B%20foo%3A%20string%20%7D%3E)
[-]Polymorphism doesn't work with Readonly args and strictFunctionTypes[/-][+]Polymorphism doesn't work with mapped type args and strictFunctionTypes[/+]weswigham commentedon Oct 19, 2018
The root cause of the issue seems to be that for
Base<T>, since it's an interface we type, we see that it matches withBase<{ foo: string }>and measure the variance of each type parameter and perform comparisons accordingly, while forChild<T>, despite it being identical toBase<T>, since it is a different reference, we do not do variance measurements, and instead fall back to structural comparisons, which fail (due to howanyworks and the type having a contravariant position).ahejlsberg commentedon Oct 26, 2018
This is fixed by #27804 because we now measure variance of
Readonly<T>and then just relate the types passed forT.