0

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.

5
  • Instead of using spread you should consider using function type as generic: Playground Commented Aug 31, 2024 at 10:11
  • Thanks - that helped. I'm now coming across another similar error downstream though when trying to pass the generated functions into their destination. Updated playground Commented Aug 31, 2024 at 12:09
  • I think I need some way to split Parameters<fn> into it's first parameter and the rest. Commented Aug 31, 2024 at 12:19
  • The spread operator you're using in RawMatcherFn means your "source" function can have more or less than the target (return type of 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 Commented Aug 31, 2024 at 13:32
  • • Does @HairyHandKerchief23 want to write an answer? • wheresrhys Note that "another similar error downstream" is either a followup question and belongs in a new post, or it's an important part of the current question and should be edited into the question above. Which one is it? Commented Aug 31, 2024 at 18:09

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.