microsoft / microsoft/TypeScript
Overload resolution selects most narrow overload when `any` is involved
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
TypeScript Version: 4.0.0-dev.20200730
Search Terms: any overload
Code
declare class Endpoint {}
declare function getEndpoint(index: number): Endpoint | undefined;
declare function getEndpoint(index: 0): Endpoint;
declare const i1: number | undefined;
const e1 = getEndpoint(i1 ?? 0); // Endpoint | undefined, as expected
declare const i2: any;
const e2 = getEndpoint(i2); // Endpoint, expected Endpoint | undefined
Expected behavior:
The type of e2 should include undefined, since we cannot know that the most narrow overload always matches.
Actual behavior:
It does not.
I understand that it is not always possible to select a sound overload, especially when the possible argument types are not strictly subsets of each other. However choosing the most narrow overload does not seem correct.
Take this extension of the repro for example:
declare class Endpoint {}
declare function getEndpoint(index: number): Endpoint | undefined;
declare function getEndpoint(index: 1 | 2): "FOOBAR";
declare function getEndpoint(index: 0): Endpoint;
declare const i3: any;
const e3 = getEndpoint(i3);
Here, e3 is inferred as Endpoint. When I change the argument in the 2nd overload to 1 instead of 1 | 2, e3 suddenly has type "FOOBAR". I would argue that it is not possible to narrow to any overload here, since i3 could be any number (or even any other type).
Therefore I believe that the most sound result would be the union of all return types, that is Endpoint | undefined | "FOOBAR".
Playground Link: Playground Link
Related Issues: none found that seems to match this one
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 TypeScript playground reproduction and trace overload resolution for calls whose argument type is any. Compare the inferred types of e2 and e3 with the expected return-type unions. Done means the reported cases no longer select only the narrowest overload and relevant compiler tests cover the 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