import { Length, PartialList, Skip } from './array'; import { Inc } from './counter'; type _CurryBasic = >(...args: T) => Skip, TArgs> extends [] ? TReturn : _CurryBasic, TArgs>, TReturn>; type CurryBasic any> = _CurryBasic, ReturnType>; // eslint-disable-next-line @typescript-eslint/no-namespace namespace R { export const __: unique symbol = Symbol('__'); }; type __ = typeof R.__; type GapOf = TProvided[i] extends __ ? [...TGapped, TTarget[i]] : TGapped; type GapsOf = i extends Length ? [...TGapped, ...Skip] : GapsOf, Inc>; type PartialGaps = T extends [infer X, ...infer Y] ? [X | __, ...PartialGaps] : []; type Gaps = PartialList>; type _CurryWithGaps = >(...args: T) => GapsOf extends [any, ...any[]] ? _CurryWithGaps, TReturn> : TReturn; type CurryWithGaps any)> = _CurryWithGaps, ReturnType>; export type Curry any)> = CurryWithGaps; function _curry(fn: (...args: any) => any, ...args: any): any { if (args.length < fn.length) { return (...subargs: any) => _curry(fn, ...args, ...subargs); } return fn(...args); } function _curry2 any>(f: F): any/*Curry*/ { const _args = Array(f.length).fill(R.__); if (!_args.length) { return f(); } let argIndex = 0; return function doit(...args: any) { for (let i = 0; i < args.length; i++) { _args[argIndex + i] = args[i]; } argIndex += args.length; if (argIndex < f.length) { return doit; } return (function tryFillGaps() { const _gaps = _args.filter(p => p === R.__); if (!_gaps.length) { return f(..._args); } let gapIndex = 0; return function fillGaps(...gaps: any) { for (let i = 0; i < gaps.length; i++) { _gaps[gapIndex + i] = gaps[i]; } gapIndex += gaps.length; if (gapIndex < _gaps.length) { return fillGaps; } while (_gaps.length) { _args[_args.lastIndexOf(R.__)] = _gaps.pop(); } return tryFillGaps(); }; }()); }; } export function curry any>(fn: TFn): Curry { return _curry(fn); } function test(a: "asdf", b: true, c: Date) { return 44; } const testc = curry(test); const testr = testc('asdf', true);//("asdf");//(new Date());