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
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:
Playground link to code