TypeScript: Make function argument conditionally optional

961 Views Asked by At

I want to have function that's take second argument only when some conditions are met.

let fn  = <T extends boolean>(arg1: T, arg2: T extends true ? void : string) => {};

fn(true); // ERROR Expected 2 arguments, but got 1
fn(true, undefined); // OK
fn(false, ''); // OK

It's weird behaviour, especially because type function argument as void doesn't force to pass in in a call. Eg:

let fn1 = (arg: void) => {};
fn1(); // OK

Playground

1

There are 1 best solutions below

1
On BEST ANSWER

This is a design limitation, see microsoft/TypeScript#29131. Treating a trailing void function parameter was treated as optional was implemented in microsoft/TypeScript#27522, but the checking for that is shallow and it doesn't work in your conditional type.

I think you might be better off using tuples in rest parameter positions to get the behavior you want, since tuples can have optional elements and even parameter name labels. Maybe something like this:

let fn = <T extends boolean>(
    arg1: T,
    ...rest: (T extends true ? [arg2?: undefined] : [arg2: string])
) => { };

fn(true); // okay
fn(true, undefined); // okay
fn(true, ''); // error
fn(false); // error
fn(false, undefined); // error
fn(false, ''); // okay

Playground link to code