Description
TypeScript Version: 3.8.3
Search Terms:
Overloading, arrow functions, type union, any
Code
const remove: {
(str: string, c: string): string
(str: string[], c: string): string[]
} = (str: string | string[], c: string) =>{
if (Array.isArray(str))
return str.map(s => s.replace(c, ''))
else
return str.replace(c, '')
}
Expected behavior:
Either the function compiles, or the version with function
also fails to compile
function remove2(str: string, c: string): string
function remove2(str: string[], c: string): string[]
function remove2(str: string | string[], c: string) {
if (Array.isArray(str))
return str.map(s => s.replace(c, ''))
else
return str.replace(c, '')
}
Actual behavior:
The following error occurs with the arrow version:
Type 'string | string[]' is not assignable to type 'string'.
Type 'string[]' is not assignable to type 'string'.(2322)
I must change the parameter of the implementation from string | string[]
to any
for the code to compile.
However, the version with function
compiles.
Playground Link:
Playground link
Related Issues:
Note that this is subtly different from #33482 where the return type of the implementing function was questioned. Here, no return type is specified. The issue is the parameter type.
I understand the error message. Instead of looking at the behavior of the function, it is simply stated that (str: string | string[], c: string) => string | string[]
is not compatible with the LHS type. That is undispably the case.
However, the function
overload traces the function behavior, finding that string
arguments lead to string return values and string[]
arguments to string[]
return values. The same could be done here: when the LHS is typed as an overload and the RHS is a literal arrow function, check whether the particular instance (and not any instance with that type) is assignable.