Skip to content

Covariant generic parameters fail unificationΒ #61503

@feedab1e

Description

@feedab1e

πŸ”Ž Search Terms

"contravariant", "unification"

πŸ•— Version & Regression Information

  • This changed between versions 3.3.3 and 3.5.1

⏯ Playground Link

https://www.typescriptlang.org/play/?jsx=0#code/MYewdgzgLgBKZQE4EMBuzEEtkJgXhgAoBKfAPhgG8AoGOcaegWwCNMwBTfGAHgGEoADzKEA+gEYAXEWCSBg0ngpgArgBs1AGhiiATNMKz5i5erXEDJmPPJErKsABMOAM3YdHMZBC9gAngDc1LT0kLBqHBAQovDQWJyeBPwwHIJQHE4+lBFgAOZQABaSqqwciAC+IrLWFjCqGrb1akF0sbBMIIgcMQxI7om8fClpGY5ZOflFJSxl2sAFGHwgzgCCUGLFKqWIFtNllYbSfLVNjWYtoYzp0OLcoKzuhBFRPWHxHtodXa9x-cQXbRg1ygujuIAenEIX26bXejm0z2isL+AN6MEQ3GB4hIQXKwUBoHQWBwsAIJFsNFaaPubE43H4QhEEkstnk2j0LKU1iEtRsXIczjcCS8PhwgWCVLCMERPz6wqSQ1S6UyVAmhU22wOvNsAtc-RFvnFksY0NlcPpipGKuyGUmGpmiDmC0QS1W61E9rKuy2Dq1Rx1Tj1wu8htRUqxYIhHCekSRvThn06MPjKJCgOBoIINMepuRCQRsbNqfKQA

πŸ’» Code

const contravariant = () => {
  const combine = <Ctx>(_1: (c:Ctx) => null, _2: (c:Ctx) => null): () => Ctx => () => undefined as any;

  const less_constrined = <C extends {length:number}>(c: C): null => null;
  const more_constrined = <C extends {length:number, charCodeAt(_:number):number}>(c: C): null => null;
  const test1 = combine(less_constrined, more_constrined);
  const test2 = combine(more_constrined, less_constrined);
}

const covariant = () => {
  const combine = <Ctx>(_1: () => Ctx, _2: () => Ctx): Ctx => undefined as any;

  const less_constrined = <C extends {length:number}>(): C => undefined as any;
  const more_constrined = <C extends {length:number, charCodeAt(_:number):number}>(): C => undefined as any;
  const test1 = combine(less_constrined, more_constrined);
  const test2 = combine(more_constrined, less_constrined);
}

πŸ™ Actual behavior

In the contravariant example the type is inferred from the first argument, so test1 fails to typecheck, despite both test1 and test2 sharing the same argument types, just reversed. This is also different from the covariant case where types are properly unified in both test1 and test2

πŸ™‚ Expected behavior

The behaviour for the covariant and contravariant case should match, so test1 should be inferred as
<C extends { length: number; charCodeAt(_: number): number; }>() => C

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: check: Type InferenceRelated to type inference performed during signature resolution or `infer` type resolutionHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions