- long, unmaintainable, unconscious
- junk code
- limited number of args (usually 5 - 10)
type Chain<In, Out, Tmp1 = any, Tmp2 = any> = []
| [(arg: In) => Out]
| [
(arg: In) => Tmp1,
(i: Tmp1) => Tmp2,
...Chain<Tmp2, Out>
];
declare function flow<In, Out>(...fns: Chain<In, Out>): Out
type Lookup<T, K extends keyof any, Else=never> = K extends keyof T ? T[K] : Else
type Tail<T extends any[]> =
((...t: T) => void) extends ((x: any, ...u: infer U) => void) ? U : never;
type Func1 = (arg: any) => any;
type ArgType<F, Else=never> = F extends (arg: infer A) => any ? A : Else;
type AsChain<F extends [Func1, ...Func1[]], G extends Func1[]= Tail<F>> =
{ [K in keyof F]: (arg: ArgType<F[K]>) => ArgType<Lookup<G, K, any>, any> };
type LastIndexOf<T extends any[]> =
((...x: T) => void) extends ((y: any, ...z: infer U) => void)
? U['length'] : never
declare function flow<F extends [(arg: any) => any, ...Array<(arg: any) => any>]>(
...f: F & AsChain<F>
): (arg: ArgType<F[0]>) => ReturnType<F[LastIndexOf<F>]>;
const badChain = flow(
(x: number)=>"string",
(y: string)=>false,
(z: number)=>"oops"
); // error, boolean not assignable to number
const stringToString = flow(
(x: string) => x.length,
(y: number) => y + "!"
); // okay
const str = stringToString("hey"); // it's a string
const tooFewParams = flow(); // error
See https://stackoverflow.com/questions/53173203/typescript-recursive-function-composition
(Now reported bug in Intellisense)
Probably no. See #27102