I have the following function with two overloads. The overloads work fine when I'm calling the function, but inside the function body, the type of the second argument is not narrowed based on the value of the first argument.
function foo(event: 'one', value: string): void;
function foo(event: 'two', value: number): void;
function foo(event: 'one' | 'two', value: string | number): void {
event // 'one' | 'two'
value // string | number
if (event === 'one') {
event // 'one'
value // !!! string | number , Why not string??
} else {
event // 'two'
value // !!! string | number , Why not number??
}
}
Is it possible to have type of value
- string
when first argument is 'one', and of type number
when first argument is 'two'?
CodePudding user response:
Yes it is if you use a union opf tuples in rest parameters and destructure the tuple right in the parameters. In fact using this you don't even need the overloads anymore, the tuple union will be preseneted as overloads:
function foo(...[event, value]:
| [event: 'one', value: string]
| [event: 'two', value: number]): void {
event // 'one' | 'two'
value // string | number
if (event === 'one') {
event // 'one'
value // string
} else {
event // 'two'
value // number
}
}
Limitations: only works if the tuple union is a discriminated union (yours is).