import { type Curried, curry } from './curry.js'; export type Purried< F extends (...args: Parameters) => ReturnType, P extends Parameters | Parameters> = Parameters | Parameters>, > = // Disallow rest parameters and optional parameters Parameters & Parameters> extends never ? // Disallow no parameters Parameters extends [unknown, unknown, ...unknown[]] ? // Generic types P extends Parameters ? F : Curried : never : never; /** * Curries a function by one level deep and overloads the original function. * Returned function can be called with both curried and non-curried parameters. * Rest parameters and optional parameters are not supported. * * @example * // ---- For non-generic typed functions ---- * // Manually type to be generic. * const pow:

>>( * ...args: P * ) => ReturnType> = purry(Math.pow); * * const result1 = pow(2, 3); // 8 * const result2 = pow(3)(2); // 8 * * @example * // ---- For generic typed functions ---- * const _map = (arr: T[], mapper: (v: T) => U): U[] => arr.map(v => mapper(v)); * * // Manually declare overloaded function to be generic. * function map( * ...args: Parameters> * ): ReturnType>; * function map( * ...args: Parameters>> * ): ReturnType>>; * function map( * ...args: Parameters>> * ): ReturnType>> { * return purry(_map)(...args); * } * * const result1 = map([1, 2], x => x * 2); // [2, 4] * const result2 = map((x: number) => x * 2)([1, 2]); // [2, 4] */ export function purry ReturnType>( fn: F, ): Purried extends never ? never :

>>(...args: P) => ReturnType> { // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- purry cannot be safely typed return ((...args: never[]) => fn.length === args.length ? fn(...args) : curry(fn)(...args)) as Purried extends never ? never :

>>(...args: P) => ReturnType>; }