localusercamp
localusercamp

Reputation: 55

Combine two functions into one

The goal here is to create one function from 2 functions with argument combination. It could be easily done with JavaScript, but it's not easy with typescript.

One way to combine two functions is Proxy. Example:

const f1 = (a: number) => {
    return (a + 1) * 2;
} 

const f2 = (b: string, c: string[]) => {
    c.push(b);
    return c;
}

const combiner = (f1: Function, f2: Function) => {
    return new Proxy(f1, {
        apply(target, thisArg, args) {
            const f1_args = args.slice(0, f1.length);
            const f2_args = args.splice(f1.length);
            f1(...f1_args);
            f2(...f2_args);
        }
    });
};

const f = combiner(f1, f2);

f(1, 'foo', ['bar']); // Typehints?

The question is could it be typed with typescript to typehint result of combiner function?

Upvotes: 3

Views: 370

Answers (1)

Tobias S.
Tobias S.

Reputation: 23835

Typing the parameters of the combined function is trivially achieved by using two generic types A1 and A2 which hold the parameter tuple types of the two functions.

const combiner = <
  A1 extends any[], 
  A2 extends any[]
>(f1: (...args: A1) => void, f2: (...args: A2) => void) => {
    return new Proxy(f1, {
        apply(target, thisArg, args) {
            const f1_args = args.slice(0, f1.length);
            const f2_args = args.splice(f1.length);
            f1(...f1_args as A1);
            f2(...f2_args as A2);
        }
    }) as unknown as (...args: [...A1, ...A2]) => void
};

We only need to assert that the returned type is a function which has the combined A1 and A2 tuples as its parameter type.

const f = combiner(f1, f2);
//    ^? const f: (a: number, b: string, c: string[]) => void

f(1, 'foo', ['bar']);

Playground

Upvotes: 1

Related Questions