I'm trying to make kind of a composer functionality based on an array of functions. The idea is:
Assuming there exists two closure function func1
and func2
both with the same number of arguments that return the same function contract, let's say:
func1(arg1: {a: number}) => (a: number) => number
func2(arg1: {b: string}) => (a: number) => number
Now, the composer function is like:
const composedFunction = compose({func1, func2});
The result of composedFunction is a function with an argument which let configure optionally the arguments to be passed to each function.
// ---------------------------- ∨ This is the value passed to the most inner function
const result = composedFunction(33, {func1: {a: 1}});
// --------------------------------- ∧ This is an object with the configuration of each function
Where the result
variable will contain the composition of the result of each function. For clarity, lets say that
const f1 = func1(...);
const f2 = func2(...);
// result will be f1(f2(33))
What have I achieved so far
type MyFunction = (value: any) => (a: number) => number;
export const compose = <T extends keyof any>(funcs: Record<T, MyFunction>) => {
...
return (
value: number,
config?: Partial<{ [K in keyof typeof funcs]: Parameters<typeof funcs[T]>[0] }>,
) => {
...
};
};
However, typescript says that for each function the configuration has a value of any
.
const result = composedFunction(33, {func1: {a: 1}});
// --------------------------------- ∧ This configuration results in Partial<{ func1: any, func2: any}>
Any ideas on how to make the types of each function arguments appear on the configuration argument?
CodePudding user response:
Here is how I would fix it:
export const compose = <T extends Record<string, MyFunction>>(funcs: T) => {
return (
value: number,
config?: Partial<{ [K in keyof T]: Parameters<T[K]>[0] }>,
) => {
};
};
You only used T
to infer the keys of the passed object. Any information about the functions passed is lost since you don't store it anywhere. When you use Parameters<typeof funcs[T]>[0]
, you will only get any
as a result since the type of funcs
is just Record<"func1" | "func2", MyFunction>
which contains no information about the specfic functions you passed.
You should instead use T
to infer the whole object with both the keys and the functions. When you use Parameters<T[K]>[0]
now, T
contains all the information about the functions.