remeda
Version:
A utility library for JavaScript and Typescript.
1 lines • 3.6 kB
Source Map (JSON)
{"version":3,"file":"partialLastBind.cjs","names":[],"sources":["../src/partialLastBind.ts"],"sourcesContent":["import type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport type { RemedaTypeError } from \"./internal/types/RemedaTypeError\";\nimport type { StrictFunction } from \"./internal/types/StrictFunction\";\nimport type { TupleSplits } from \"./internal/types/TupleSplits\";\n\ntype PartialLastBindError<\n Message extends string,\n Metadata = never,\n> = RemedaTypeError<\"partialLastBind\", Message, { metadata: Metadata }>;\n\ntype TupleSuffix<T extends IterableContainer> = TupleSplits<T>[\"right\"];\n\ntype RemoveSuffix<\n T extends IterableContainer,\n Suffix extends TupleSuffix<T>,\n> = Suffix extends readonly []\n ? T\n : T extends readonly [...infer TRest, infer TLast]\n ? Suffix extends readonly [...infer SuffixRest, infer _SuffixLast]\n ? // SuffixLast extends TLast.\n RemoveSuffix<TRest, SuffixRest>\n : // Suffix (as a whole) extends ReadonlyArray<TLast>.\n // Suffix could possibly be empty, so this has to be TLast?.\n [...RemoveSuffix<TRest, Suffix>, TLast?]\n : // T has an optional or rest parameter last. If T is a parameter list,\n // this can only happen if we have optional arguments or a rest param;\n // both cases are similar.\n T extends readonly [...infer TRest, (infer _TLast)?]\n ? Suffix extends readonly [...infer SuffixRest, infer _SuffixLast]\n ? // SuffixLast extends TLast.\n RemoveSuffix<TRest, SuffixRest>\n : // Suffix (as a whole) extends [...TRest, TLast?].\n TRest\n : // We got passed a parameter list that isn't what we expected; this\n // is an internal error.\n PartialLastBindError<\"Function parameter list has unexpected shape\", T>;\n\n/**\n * Creates a function that calls `func` with `partial` put after the arguments\n * it receives. Note that this doesn't support functions with both optional\n * and rest parameters.\n *\n * Can be thought of as \"freezing\" some portion of a function's arguments,\n * resulting in a new function with a simplified signature.\n *\n * Useful for converting a data-first function to a data-last one.\n *\n * @param func - The function to wrap.\n * @param partial - The arguments to put after.\n * @returns A partially bound function.\n * @signature\n * R.partialLastBind(func, ...partial);\n * @example\n * const fn = (x: number, y: number, z: number) => x * 100 + y * 10 + z;\n * const partialFn = R.partialLastBind(fn, 2, 3);\n * partialFn(1); //=> 123\n *\n * const parseBinary = R.partialLastBind(parseInt, \"2\");\n * parseBinary(\"101\"); //=> 5\n *\n * R.pipe(\n * { a: 1 },\n * // instead of (arg) => JSON.stringify(arg, null, 2)\n * R.partialLastBind(JSON.stringify, null, 2),\n * ); //=> '{\\n \"a\": 1\\n}'\n * @dataFirst\n * @category Function\n * @see partialBind\n */\nexport function partialLastBind<\n F extends StrictFunction,\n SuffixArgs extends TupleSuffix<Parameters<F>>,\n RemovedSuffix extends RemoveSuffix<Parameters<F>, SuffixArgs>,\n>(\n func: F,\n ...partial: SuffixArgs\n): (\n ...rest: RemovedSuffix extends IterableContainer ? RemovedSuffix : never\n) => ReturnType<F> {\n // @ts-expect-error [ts2345, ts2322] -- TypeScript infers the generic sub-\n // types too eagerly, making itself blind to the fact that the types match\n // here.\n return (...rest) => func(...rest, ...partial);\n}\n"],"mappings":"AAqEA,SAAgB,EAKd,EACA,GAAG,EAGc,CAIjB,OAAQ,GAAG,IAAS,EAAK,GAAG,EAAM,GAAG,EAAQ"}