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');
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!