Reputation: 1454
I'm writing a function that calls another function that have enums as accepted parameters. Depending on the value passed, the return type from the function differs.
The function being called (b) and function calling (a) will both need to have their parameters conforming to the enum. I wonder why the following code gives a Tyepscript error?
export function a (mode: 'a' | 'b') {
return b(mode)
}
export function b (mode: 'a'): string
export function b (mode: 'b'): number
export function b (mode: 'a' | 'b'): string | number {
return (mode=='a') ? 'string' : 1;
}
Error:
No overload matches this call.
Overload 1 of 2, '(mode: "a"): string', gave the following error.
Argument of type '"a" | "b"' is not assignable to parameter of type '"a"'.
Type '"b"' is not assignable to type '"a"'.
Overload 2 of 2, '(mode: "b"): number', gave the following error.
Argument of type '"a" | "b"' is not assignable to parameter of type '"b"'.
Type '"a"' is not assignable to type '"b"'.ts(2769)
Cart.tsx(118, 18): The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.
Closest question is here, but I don't want to have a signature that is ambiguous - mode 'a' should always return string, and 'b' always number.
Upvotes: 2
Views: 4357
Reputation: 8380
This problem arises from time to time. And even in the same form as your question. I believe that's the main place to track progress by now. But there is no built-in solution yet.
As for now you may just add a unified overload or implement something like proposed by jcalz in one of the issues.
Upvotes: 1
Reputation: 1580
The combined function signature (b (mode: 'a' | 'b'): string | number
) is not visible at all to callers. As far as Typescript compiler is concerned, only b (mode: 'a'): string
and b (mode: 'b'): number
exist. This is also what the last line of the error message means.
One example that might help explain why this is not possible is event listeners: addEventListener('click')
and addEventListener('keyDown')
is not the same as addEventListener('click' | 'keyDown')
. Accordingly, the two signatures are completely separate and you either need an if statement with two separate calls or an additional signature with the union type to fix the error.
Upvotes: 0