|
| 1 | +type DynamicParamsCurrying<F> = F extends (...args: infer P) => infer R |
| 2 | + ? <T extends unknown[]>( |
| 3 | + ...args: P extends [...T, ...unknown[]] ? T : [] |
| 4 | + ) => P extends [...T, ...infer Rest] |
| 5 | + ? DynamicParamsCurrying<(...args: Rest) => R> |
| 6 | + : DynamicParamsCurrying<F> |
| 7 | + : never; |
| 8 | + |
| 9 | +declare function DynamicParamsCurrying<F>(fn: F): DynamicParamsCurrying<F>; |
| 10 | + |
| 11 | +// ------------------- Test section --------------------- |
| 12 | + |
| 13 | +const originalCurry = ( |
| 14 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 15 | + ingredient1: number, |
| 16 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 17 | + ingredient2: string, |
| 18 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 19 | + ingredient3: boolean, |
| 20 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 21 | + ingredient4: Date, |
| 22 | +) => true; |
| 23 | + |
| 24 | +const spikedCurry = DynamicParamsCurrying(originalCurry); |
| 25 | + |
| 26 | +// Direct call |
| 27 | +const t0 = spikedCurry(0, "Ziltoid", true, new Date()); |
| 28 | + |
| 29 | +// Partially applied |
| 30 | +const t1 = spikedCurry(1)("The", false, new Date()); |
| 31 | + |
| 32 | +// Another partial |
| 33 | +const t2 = spikedCurry(0, "Omniscient", true)(new Date()); |
| 34 | + |
| 35 | +// You can keep callin' until the cows come home: it'll wait for the last argument |
| 36 | +const t3 = spikedCurry()()()()(0, "Captain", true)()()()(new Date()); |
| 37 | + |
| 38 | +// currying is ok |
| 39 | +const t4 = spikedCurry(0, "Spectacular", true); |
| 40 | + |
| 41 | +// @ts-expect-error arguments provided in the wrong order |
| 42 | +const e0 = spikedCurry("Nebulo9", 0, true)(new Date()); |
0 commit comments