microsoft / microsoft/TypeScript
Covariant generic parameters fail unification
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- PR merge metrics
- PR metrics pending
Description
### 🔎 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
```ts
const contravariant = () => {
const combine = (_1: (c:Ctx) => null, _2: (c:Ctx) => null): () => Ctx => () => undefined as any;
const less_constrined = (c: C): null => null;
const more_constrined = (c: C): null => null;
const test1 = combine(less_constrined, more_constrined);
const test2 = combine(more_constrined, less_constrined);
}
const covariant = () => {
const combine = (_1: () => Ctx, _2: () => Ctx): Ctx => undefined as any;
const less_constrined = (): C => undefined as any;
const more_constrined = (): 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
`
### Additional information about the issue
_No response_
Contributor guide
Research direction
Start with the linked TypeScript Playground repro and compare the contravariant calls with the covariant calls, including the reported behavior between versions 3.3.3 and 3.5.1. The issue is done when both argument orders unify consistently and the first contravariant call infers the more constrained C type shown in the expected behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100