I have an object of methods which I am seeking to extend with copies of those methods but scoped to a given method e.g. the method fetchOnce()
will have copies postOnce()
, getOnce()
etc.
The original methods have different numbers of parameters, so I am using generics to enable me to have a single utility function that creates these copies. See below for a simplified example:
const funcs = {
simple: (
options: object,
): boolean => {
return true
},
times: (
times: number,
options: object,
): boolean => {
return true
},
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function scopeFuncToMethod<Args extends any[]>(
func: (...args: Args) => boolean,
method: string,
): (...args: Args) => boolean {
return (...args) => {
const opts = args[func.length - 1] || {};
args[func.length - 1] = { ...opts, method };
return func(...args);
};
}
scopeFuncToMethod(funcs.simple, 'get'); // no type error
scopeFuncToMethod(funcs.times, 'get'); // no type error
Object.values(funcs).map((func) => [
'getted',
scopeFuncToMethod(func, 'get'),
])
Note that there is no type error when I apply the helper to each method individually, but I get the following type error for the final scopeFuncToMethod(func, 'get')
statement if called within a loop:
Argument of type '((options: object) => boolean) | ((times: number, options: object) => boolean)' is not assignable to parameter of type '(options: object) => boolean'.
Type '(times: number, options: object) => boolean' is not assignable to type '(options: object) => boolean'.
Target signature provides too few arguments.Expected 2 or more, but got 1.ts(2345)
(
I'm unsure why this error would happen even while using generics. What can I do to fix it? I've been wondering about using a type guard within the loop, but I'm not sure it would work and it would also force me to add so much extra code that it negates the benefits of having a generic utility.
Parameters<fn>
into it's first parameter and the rest.scopeFuncToMethod
in case there's two arguments) which requires exactly 2 parameters, it's only failing the right side of the union. Fortunately there's a solution: Playground