Allow calls to overloaded functions when all possible combinations of union type parameters resolve to valid overloads
See original GitHub issueTypeScript Version: 2.4.1
Code
Case 1
// overloaded functions
declare function f(a: number): number;
declare function f(a: string): string;
function g<T extends number | string>(a: T) {
return f(a); // either of arguments is acceptable
// ~
// Argument of type 'T' is not assignable to parameter of type 'string'.
// Type 'string | number' is not assignable to type 'string'.
// Type 'number' is not assignable to type 'string'.
}
Case 2
declare function f2<T>(a: Promise<T>): number;
declare function f2<T>(a: T): string;
function g2<T>(a: T) {
const result: string = f2(a); // first overload is ignored, but the argument can be a Promise
return result;
}
Expected behavior:
Case 1: compiles with no errors
Case 2: error that type string | number
is not assignable to type string
Actual behavior:
Case 1: error
Argument of type 'T' is not assignable to parameter of type 'string'.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'
Case 2: compiles without errors
Note
I remember here were some discussions about that, so that verifying all possible paths may result in N*M complexity (N overloads, M constituent types in unions). I could not find it.
The second case seems unsafe at all, because skips a possibly valid overload which may effect on return type. I expect that f2(a)
would be of type number | string
because either of these two overloads can play. It actually has the same result with a: any
.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:18 (14 by maintainers)
Top Results From Across the Web
python - mypy error, overload with Union/Optional ...
In short, if you run mypy with the --no-strict-optional flag, you're instructing mypy to assume that 'None' is a valid member of every...
Read more >Groovy Language Documentation
Type checking assignments; List and map constructors; Method resolution ... Groovy allows you to overload the various operators so that they can be...
Read more >The Definitive TypeScript 4.8 Guide - SitePen
The TypeScript compiler is highly configurable, allowing the user to ... write an overload for every number of arguments that the function ......
Read more >typescript-cheatsheet - GitHub Pages
Tuple types allow you to express an array where the type of a fixed number ... In TypeScript any argument of a function...
Read more >6 SWIG and C++
When wrapping C++ code, it is critical that SWIG be called with the `-c++' option. ... SWIG will wrap all types of functions...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I was talking to @ahejlsberg about something like this a few days ago. Maybe we can bring it up again.
Oh, my interpretation had been that propagating the overload would mean storing the different possible outcomes, which may sound manageable in this toy example, but perhaps less so if we’d be nesting calls with respectively
n
,i
,j
overloads, making forn * i * j
potential overloads throughout the evaluation from the top level.I’m thinking we might not necessarily need much more complexity. Knowing:
RegExp
tov
T
would beRegExp
as well… then if rather than
<T>(v: T) => Match(T)
we’d be evaluating the return type of signature<T>(v: T extends RegExp) => Match(T)
instead, I’m thinking that might already suffice to evaluate toMatch(RegExp)
->0
.