_curry.js.flow 1.2 KB

1234567891011121314151617181920212223242526272829
  1. // @flow
  2. // Type definitions taken from https://github.com/gcanti/flow-static-land/blob/master/src/Fun.js
  3. type Fn1<A, B> = (a: A, ...rest: Array<void>) => B
  4. type Fn2<A, B, C> = (a: A, b: B, ...rest: Array<void>) => C
  5. type Fn3<A, B, C, D> = (a: A, b: B, c: C, ...rest: Array<void>) => D
  6. type CurriedFn2<A, B, C> = Fn1<A, Fn1<B, C>> & Fn2<A, B, C>
  7. // eslint-disable-next-line no-unused-vars
  8. type CurriedFn3<A, B, C, D> = Fn1<A, CurriedFn2<B, C, D>> & Fn2<A, B, Fn1<C, D>> & Fn3<A, B, C, D>
  9. // eslint-disable-next-line no-unused-vars
  10. declare function curry<A, B, C>(f: Fn2<A, B, C>): CurriedFn2<A, B, C>
  11. // eslint-disable-next-line no-redeclare
  12. declare function curry<A, B, C, D>(f: Fn3<A, B, C, D>): CurriedFn3<A, B, C, D>
  13. function curried(f: Function, length: number, acc: Array<any>): Function {
  14. return function fn() {
  15. // eslint-disable-next-line prefer-rest-params
  16. const combined = acc.concat(Array.prototype.slice.call(arguments))
  17. return combined.length >= length ? f.apply(this, combined) : curried(f, length, combined)
  18. }
  19. }
  20. // eslint-disable-next-line no-redeclare
  21. export default function curry(f: Function): Function {
  22. // eslint-disable-line no-redeclare
  23. return curried(f, f.length, [])
  24. }