Home > Software design >  How to pass function and arguments of that function as parameters in typescript
How to pass function and arguments of that function as parameters in typescript

Time:11-20

How can I define a function in typescript that takes a function as the first parameter, and the arguments for that function as the second parameter, while maintaining the strong typing of the function passed as the first parameter?

For example, say I have three functions defined as follows:

const firstFunc = (param1: string, param2: number): string;
const secondFunc = (param1: boolean): void;
const thirdFunc = (): number;

I'd like to create a function like this (not working code):

const myFunc = (someFunc: () => any, params: []) => {
  return someFunc(...params);
}

Then if I were to pass firstFunc into myFunc, it should require params to be a string and a number, and expect to return a string. If I passed secondFunc into myFunc, it should require params to be a boolean, and expect to return void, and if I pass thirdFunc, it should be fine with nothing passed to params, and expect to return a number.

Is something like this possible?

CodePudding user response:

This should do it:

const callMeMaybe = <T extends (...args: any[]) => any>(f: T, ...args: Parameters<T>): ReturnType<T> => {
  return f(...args);
}

const heyIJustMetYou = (a: number, b: string): string => b.repeat(a)

// errors as expected
const andThisIsCrazy = callMeMaybe(heyIJustMetYou, 3);

// Has type string
const butHeresMyNumberSo = callMeMaybe(heyIJustMetYou, 3, 'a');

Playground

Note that this doesn't work if f is itself generic. Also note that this isn't terribly useful. But you could make it return a thunk, and that would probably be more useful:

const thunkify = <T extends (...args: any[]) => any>(f: T, ...args: Parameters<T>): () => ReturnType<T> => {
  return () => f(...args);
}

...which returns a function that when called will call f with its arguments. This can be used to delay evaluation of f.

UPDATE

Better version, courtesy of jcalz in the comments:

const callMeMaybe = <A extends any[], R>(f: (...args: A) => R, ...args: A): R => {
  return f(...args);
}

Properly handles generic functions!

  • Related