Reputation: 2317
I am trying to type the following function:
function foo(input, modifier, merge) {
return merge(...modifier.map(m => m(input)));
}
The objective is to have the correct types for the parameters of the merge
function.
Context:
modifier
is an array of function with a single parameter of the type of typeof input
and a different return type for each functionmerge
is a function, which has modifier.length
parameters, with the parameter at position n having the same type as the return type of the function modifier[n]
and returns a singe (generic) valueHow can this be done?
Possible with objects (Record<K,V>
):
// for Functions (here type Func)
type Func = () => any;
// a mapping of a string key to an function can be created
type FuncMap = Record<string, Func>;
// for this mapping you can create a mapping to the return types of each function
type ReturnTypeMap<T extends FuncMap> = { [K in keyof T]: ReturnType<T[K]> }
Is something like this also possible for arrays, based on the position instead of a object key?
This is my attempt at the typing the function, but i don't know how to use ReturnType in combination with arrays:
function foo<I, M extends Array<(input: I) => any>, O>(
input: I,
modifier: M,
merge: (...args: ReturnType<M>) => O
// ^^^^^^^^^^^^^ this is not working, since relation to each item is missing
): O {
return merge(...modifier.map(m => m(input)));
}
Upvotes: 3
Views: 2072
Reputation: 10565
Do it like this I think:
type ExtractReturnTypes<T extends readonly ((i: any) => any)[]> = [
... {
[K in keyof T]: T[K] extends ((i: any) => infer R) ? R : never
}
];
function foo<I, M extends readonly ((i: I) => any)[], O>(
input: I,
modifiers: M,
merge: (...args: ExtractReturnTypes<M>) => O
) {}
foo(
1,
[(i: number) => 5, (i: number) => 'b' as const] as const,
// a has type: number
// b has type: 'b'
(a, b) => 'test'
);
Upvotes: 2