Lukor
Lukor

Reputation: 1727

Function parameter type depending on type of other parameter

I am trying to write a function which has the following type signature:

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?

EDIT: Complete example: https://typescript-play.js.org/#code/GYVwdgxgLglg9mABAWwJ4DFzXmAPADUQFMAPKIsAEwGdFqoAnGMAc0QB9FxKjhmjKAPgAUAKEQTEAQwBcifABpxkgEZzCpclVrde-SogD8iMCGQqiDRHPpNWSgJSIA3sokxgiYVMQBCALz+XFR6YAJOrpJRiAD0MdKIMLQ+tsxsALSCiCooIPTSADbUcNlECamsbtEqAHTUAA4FMFDCAOStDgDcVQC+oj1AA

Upvotes: 3

Views: 926

Answers (2)

Johannes Klau&#223;
Johannes Klau&#223;

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

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

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

Related Questions