Reputation: 55
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
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']);
Upvotes: 1