export interface OneMore { (): OneMore (t: T): R } export interface TwoMore { (): TwoMore (t1: T1): OneMore (t1: T1, t2: T2): R } export interface ThreeMore { (): ThreeMore (t1: T1): TwoMore (t1: T1, t2: T2): OneMore (t1: T1, t2: T2, t3: T3): R } /** * Takes a function with 1 argument and returns a curried version of it * * @export * @template A * @template B * @param {(a: A) => B} f * @returns {OneMore} */ export function curry1 (f: (a: A) => B): OneMore { function curried (a: A): OneMore | B { switch (arguments.length) { case 0: return curried as OneMore case 1: return f(a) as B default: return curried as OneMore } } return curried as OneMore } /** * Takes a function with 2 arguments and returns a curried version of it * * @export * @template A * @template B * @template C * @param {(a: A, b: B) => C} f * @returns {TwoMore} */ export function curry2 (f: (a: A, b: B) => C): TwoMore { function curried (a?: A, b?: B): TwoMore | OneMore | C { switch (arguments.length) { case 0: return curried as TwoMore case 1: return curry1((b: B) => f(a, b)) as OneMore case 2: return f(a, b) as C default: return curried as TwoMore } } return curried as TwoMore } /** * Takes a function with 3 arguments and returns a curried version * * @export * @template A * @template B * @template C * @template D * @param {(a: A, b: B, c: C) => D} f * @returns {ThreeMore} */ export function curry3 (f: (a: A, b: B, c: C) => D): ThreeMore { function curried (a?: A, b?: B, c?: C): ThreeMore | TwoMore | OneMore | D { switch (arguments.length) { case 0: return curried as ThreeMore case 1: return curry2((b: B, c: C) => f(a, b, c)) as TwoMore case 2: return curry1((c: C) => f(a, b, c)) as OneMore case 3: return f(a, b, c) as D default: return curried as ThreeMore } } return curried as ThreeMore }