microsoft / microsoft/TypeScript
Overload causes generic function to loose type specificity
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.4k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
Bug Report
🔎 Search Terms
generic overloaded function type narrowing
🕗 Version & Regression Information
- This is the behavior in every version I tried (4.8, 4.9)
⏯ Playground Link
💻 Code
interface A {
a: 1;
}
interface B extends A {
b: 2;
}
interface Wrapper1<T extends A> {
value: T;
}
interface Wrapper2<T extends A> {
value: T;
}
function unwrap<T extends A>(wrapped: Wrapper1<T>): T
function unwrap<T extends A>(wrapped: Wrapper2<T>): T // Comment out this line, and types will become inferred correctly
function unwrap<T extends A>(wrapped: Wrapper1<T> | Wrapper2<T>): T {
return wrapped.value;
}
const b: B = { a: 1, b: 2 };
const wrapped: Wrapper1<B> = { value: b }
const test1 = unwrap(wrapped); // test1: B (correct)
const test2 = Promise.resolve(wrapped).then(unwrap); // test2: Promise<A> (should be Promise<B>)
const test3 = [wrapped].map(unwrap); // test3: A[] (should be B[])
🙁 Actual behavior
In test2 and test3, the generic type of the overloaded function unwrap looses it's specificity. The types can be narrowed to Promise<B> and B[] respectively, but actually it is inferred as Promise<A> and A[] respectively. Removing the one of the overloads of the function unwrap (so it is no longer overloaded) will resolve the problem.
🙂 Expected behavior
As explained above, the inferred types of test2 and test3 should be inferred as Promise<B> and B[] respectively.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground reproduction and compare inference for test1, test2, and test3 when both overloads are present. Trace the generic overload and type-inference behavior involved; done means test2 is Promise and test3 is B[] without removing an overload.
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