Skip to content
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

Polymorphism doesn't work with mapped type args and strictFunctionTypes #27984

Closed
diegohaz opened this issue Oct 19, 2018 · 3 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@diegohaz
Copy link

diegohaz commented Oct 19, 2018

TypeScript Version: 3.2.0-dev.20181019

Search Terms: readonly polymorphism mapped types interface extend

Code

interface Base<P> {
    method: (args: Readonly<P>) => void;
}

function fn(arg: Base<any>) { }

// It works
fn({} as Base<{ foo: string }>)

// Why error?
interface Child<P> extends Base<P> { }
fn({} as Child<{ 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>'.

Playground Link:
Enable strictFunctionTypes in Options:
https://www.typescriptlang.org/play/index.html#src=interface%20Base%3CP%3E%20%7B%0D%0A%20%20%20%20method%3A%20(args%3A%20Readonly%3CP%3E)%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)

Related Issues:
Maybe related to #27484

@diegohaz diegohaz changed the title Polymorphism doesn't work with Readonly args and strictFunctionTypes Polymorphism doesn't work with mapped type args and strictFunctionTypes Oct 19, 2018
@weswigham weswigham added the Bug A bug in TypeScript label Oct 19, 2018
@weswigham
Copy link
Member

weswigham commented 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).

@ahejlsberg
Copy link
Member

This is fixed by #27804 because we now measure variance of Readonly<T> and then just relate the types passed for T.

@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Oct 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants