typescripttypesconditional-typestypescript-conditional-types

Optional parameters based on conditional types


Is it possible to make a function have either mandatory or optional parameters based on conditional types in TypeScript?

This is what I've got so far:

const foo = <T extends string | number>(
    first: T,
    second: T extends string ? boolean : undefined
) => undefined;

foo('foo', true); // ok, as intended
foo(2, true); // not ok, as intended
foo(2, undefined); // ok, as intended
foo(2); // compiler error! I want this to be ok

Solution

  • You can do this in 3.1 using Tuples in rest parameters and spread expressions

    const foo = <T extends string | number>(
      first: T, 
      ...a: (T extends string ? [boolean] : [undefined?])
    ) => undefined;
    
    foo('foo', true); // ok, as intended
    foo(2, true); // not ok, as intended
    foo(2, undefined); // ok, as intended
    foo(2); // ok
    

    But the better way is to use overloads.

    function foo2(first: string, second: boolean) : undefined
    function foo2(first: number, second?: undefined): undefined
    function foo2<T>(first: T, second?: boolean): undefined{
      return undefined
    }
    
    foo2('foo', true); // ok, as intended
    foo2(2, true); // not ok, as intended
    foo2(2, undefined); // ok, as intended
    foo2(2); // ok