In Typescript, is there a way to express an array with the following property?
[
[0]: function(in: A): B;
[1]: function(in: B): C;
[2]: function(in: C): D;
...etc.
]
Basically, an array of functions where the next function accepts the returned value of the last. I'd like to use this for a Koa router, where an array of middleware can be supplied. This way, the input could be validated in one middleware function and then be used without casting in the next.
There is no way to do this easily, you firstly need a function to help with inference (variables can't declare type variables). Secondly, you need as many overloads as number of functions you want to support.
A solution could look something like this:
function compose<A, R1, R2, R3, R4>(fn1: (a: A) => R1, fn2: (a: R1) => R2, fn3: (a: R2) => R3, fn4: (a: R3) => R4): [typeof fn1, typeof fn2, typeof fn3, typeof fn4]
function compose<A, R1, R2, R3>(fn1: (a: A) => R1, fn2: (a: R1) => R2, fn3: (a: R2) => R3): [typeof fn1, typeof fn2, typeof fn3]
function compose<A, R1, R2>(fn1: (a: A)=> R1, fn2: (a: R1) => R2) : [typeof fn1, typeof fn2]
function compose(...fns: Array<(a: any) => any>) {
return fns;
}
// fns is [(a: string) => string, (a: string) => number, (a: number) => string]
let fns = compose(
(s: string) => s.toUpperCase(),
s => +s,
n => n.toExponential()
)