'How should the lodash flow function be typed in typescript?

lodash.flow combines two or more functions.

lodash.flow(double, addTwo) would return a function the would double and add two. How should this function be typed in typescript (the current definition just returns Function)?

declare function flow<In, Intermediate, Out>(f1: (a1: In) => Intermediate, f2: (a1: Intermediate) => Out): (a1: In)=> Out works for two functions with the first having one input argument. I'm not sure how to extend the definition to work in all cases.

My attempt can support mulitple functions if called like this:

lodash.flow(f1, lodash.flow(f2, f3))

but am looking for

lodash.flow(f1, f2, f3)



Solution 1:[1]

here's a way to kind of do it using conditional types:

const compose =
  <T1, T2>(f1: (p: T1) => T2) =>
  <T3>(f2: (p: T2) => T3) =>
  (p: T1) =>
    f2(f1(p));

const flow = <T1, T2, T3 = "?", T4 = "?">(
  f0: (p: T1) => T2,
  ...f: [] | [(p: T2) => T3] | [(p: T2) => T3, (p: T3) => T4]
): ((p: T1) => T3 extends "?" ? T2 : T4 extends "?" ? T3 : T4) => {
  if (f[1]) {
    return compose(compose(f0)(f[0]!))(f[1]) as any;
  }

  if (f[0]) {
    return compose(f0)(f[0]) as any;
  }

  return f0 as any;
};

in this example, flow supports up to 3 args, but it can be extended to as many as you like.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nitsan Avni