Reputation: 1727
I am trying to write a function which has the following type signature:
a
is either of type string
or undefined
b
is a string
if a
is also a string
, otherwise it is a number
My approach up to now was the following:
function myFunction<X extends string | undefined>(
a: X,
b: X extends undefined ? number : string,
) {
// ... do stuff ...
}
Calling myFunction
works just as expected, ie. myFunction('a', 'b')
works while myFunction(undefined, 'b')
throws an error. However, when I try to use the parameters in the function body, I don't have any typing support:
function myFunction<...>(...) {
if (a !== undefined) {
// a is a string -> b must also be a string
b.split(''); // -> Property 'split' does not exist on type 'X'
}
}
Do I have to cast inside my function or can I somehow convince typescript to infer my type?
Upvotes: 3
Views: 926
Reputation: 11040
Overloading the function is the way to go here. Also, remember that all your TypeScript types will be lost during transpiling to JavaScript. So conditional typing isn't really possible, since this would be a runtime check. You have to write those checks yourself.
It would also be better to bring the parameter a to the second position and make it optional, then you can write a clean check:
function myFunction(b: string | number, a?: string) {
if(typeof a !== "undefined") {
b = b as string;
b.split("");
}
}
Upvotes: 0
Reputation: 250266
Typescript does not support narrowing parameters one based on another. As far as the compiler is concerned a
and b
are independent and checking a
will not impact the type of b
even if the conditional type ties them together conceptually.
Upvotes: 1