type Func = (...a: T) => R /** * Composes single-argument functions from right to left. The rightmost * function can take multiple arguments as it provides the signature for the * resulting composite function. * * @param funcs The functions to compose. * @returns A function obtained by composing the argument functions from right * to left. For example, `compose(f, g, h)` is identical to doing * `(...args) => f(g(h(...args)))`. */ export default function compose(): (a: R) => R export default function compose(f: F): F /* two functions */ export default function compose( f1: (a: A) => R, f2: Func ): Func /* three functions */ export default function compose( f1: (b: B) => R, f2: (a: A) => B, f3: Func ): Func /* four functions */ export default function compose( f1: (c: C) => R, f2: (b: B) => C, f3: (a: A) => B, f4: Func ): Func /* rest */ export default function compose( f1: (a: any) => R, ...funcs: Function[] ): (...args: any[]) => R export default function compose(...funcs: Function[]): (...args: any[]) => R export default function compose(...funcs: Function[]) { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line return (arg: T) => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce( (a, b) => (...args: any) => a(b(...args)) ) }