Having several functions, I would like do not call them if there is no need (logic in needToCalculate
), used by a generic function calculateIfNeeded
// helper functions
function sum(a: number, b: number) { return a b; } // complex real logic (CRL)
function bum(a: number, code: string) { return (code=="B") ? a*a : a a; } // CRL
function zum(code: string) { return (code=="Z") ? 5 : 8; } // CRL
function needToCalculate(code: string) {return false} // CRL
Question: what type should have the param func
of the method calculateIfNeeded
bellow?
// calculator function
function calculateIfNeeded(code: string, func: ???, ...args: any[]){
return needToCalculate(code) ? func(args): NaN
}
// main function
let a = 4, b = 9
let res = calculateIfNeeded("A", sum, a, b); console.log(res);
res = calculateIfNeeded("B", bum, a, "B"); console.log(res);
res = calculateIfNeeded("C", zum, "Z"); console.log(res);
CodePudding user response:
since it looks like you can return anything from the calculation (assuming you're not limited by any restrictions), the type of func
will be
func: (...args: any[]) => any
That means you expected to receive in func
any number of arguments with any type, and expect to return from func
any type.
EDIT (inspired by @Dima Parzhitsky comment):
You can so something like this:
function calculateIfNeeded<F extends any[]>(code: string, func: (...args: F)=>number, ...args: F) : number{
return needToCalculate(code) ? func(...args): NaN
}
Define F
to be some extension of any arguments (any[]
).
Then the func
receives F
and return any
, and the args themselves are F
as well.
Then you just call func(...args)
CodePudding user response:
Extending upon my comment, you
/**
* This represents not just _any function_, but one that can be
* given as the second parameter (`func`) of `calculateIfNeeded`.
* The call signature must be added explicitly, because apparently
* TypeScript cannot know, that a union of callables is also callable
*/
type Func = (typeof sum | typeof bum | typeof zum) & ((...args: never[]) => number);
function calculateIfNeeded<F extends Func>(code: string, func: F, ...args: Parameters<F>): number {
return needToCalculate(code) ? func(...args): NaN;
}
Note, that I had to change func(args)
to func(...args)
, because args
is an array, but neither of sum
, bum
, or zum
accepts an array as an argument.