Say I have an array of function where each function accepts the return value of the previous function and I call Array#reduce
on that function with an initial value which the first function in the array accepts. This is perfectly sound and I would expect the return type to be the return type of the last function.
However TypeScript will not allow me to do this (see playground).
More pragmatically, I’m trying to write a generic pipe
function which will compose the functions given as the ...rest
and “pipe” the first argument into the composed function:
function pipe(source, ...fns) {
return fns.reduce((value, fn) => fn(value), source);
}
And I simply cannot find a way to type this, even with varadic tuple types.
Even if I try to write out the function recursively I’m not really sure how to type it:
function pipe<
S,
R,
Fns extends readonly unknown[],
>(source: S, ...fns: [(source: S) => R, ...Fns]): R {
if (fns.length === 0) {
return source;
}
const [fn, ...rest] = fns;
return pipe(fn(source), rest);
}
Does it work for you ?
Playground
Here, in my blog, you can find an explanation. Let me know if you are still interested in this question, I will try to provide more examplations or examples.