Modify each member of a function overload

12 views Asked by At

Given the following overloaded function:

function fooBar(param1: string, param2: number): number;
function fooBar(param1: boolean): number;
function fooBar(boolOrString: boolean | string, param2?: number): number {
  if (typeof boolOrString === 'string') {
    return boolOrString.length + param2!;
  }
  return boolOrString ? 100 : -100;
}

I would like to provide a type which changes the return type of the function to void without loosing information about the overload.

I've tried something like this:

type VoidFn<F> = F extends ((...args: infer Args) => any) | never
   ? (...args: Args) => void
   : F extends infer F1 | infer F2
   ? VoidFn<F1> | VoidFn<F2>
   : never;

However, it only resolves to the type of the last overload with the void return type:

type FV = VoidFn<typeof fooBar>
// (param1: boolean): void;

Is it possible to create a type which changes all the overloads? I've assumed that overloads are represented as union types in Typescript. Is this assumption correct?


Solution

Include the most general overload as the last one, and this is what typescript would pick:

function fooBar(param1: string, param2: number): number;
function fooBar(param1: boolean): number;
function fooBar(boolOrString: boolean | string, param2?: number): number;
function fooBar(boolOrString: boolean | string, param2?: number): number {
  if (typeof boolOrString === 'string') {
    return boolOrString.length + param2!;
  }
  return boolOrString ? 100 : -100;
}

The VoidFn type should be declared simply as:

type VoidFn<F> = F extends ((...args: infer Args) => any) ? ((...args: Args) => void) : never
0

There are 0 answers