UNPKG

remeda

Version:

A utility library for JavaScript and Typescript.

1 lines 4.04 kB
{"version":3,"file":"times.cjs","names":["purry"],"sources":["../src/times.ts"],"sourcesContent":["import type { GreaterThan } from \"type-fest\";\nimport { purry } from \"./purry\";\n\n// This number was picked by trial-and-error until typescript stops failing with\n// \"Type instantiation is excessively deep and possibly infinite. (ts2589)\".\n// See the type tests for more information.\ntype MAX_LITERAL_SIZE = 46;\n\ntype TimesArray<\n T,\n N extends number,\n Iteration extends ReadonlyArray<unknown> = [],\n> = number extends N\n ? // N is not a literal number, we can't deduce the type\n Array<T>\n : `${N}` extends `-${number}`\n ? // N is non-positive, the mapper will never run\n []\n : `${N}` extends `${infer K extends number}.${number}`\n ? // N is not an integer, we \"floor\" the number.\n TimesArray<T, K, Iteration>\n : GreaterThan<N, MAX_LITERAL_SIZE> extends true\n ? // We can't build a literal tuple beyond this size, after that we\n // can't add more items to the tuple so we add a rest element instead.\n [...TimesArray<T, MAX_LITERAL_SIZE, Iteration>, ...Array<T>]\n : N extends Iteration[\"length\"]\n ? // We finished building the output tuple\n []\n : // Add another item to the tuple and recurse.\n [T, ...TimesArray<T, N, [unknown, ...Iteration]>];\n\n/**\n * Calls an input function `n` times, returning an array containing the results\n * of those function calls.\n *\n * `fn` is passed one argument: The current value of `n`, which begins at `0`\n * and is gradually incremented to `n - 1`.\n *\n * @param count - A value between `0` and `n - 1`. Increments after each\n * function call.\n * @param fn - The function to invoke. Passed one argument, the current value of\n * `n`.\n * @returns An array containing the return values of all calls to `fn`.\n * @signature\n * R.times(count, fn)\n * @example\n * R.times(5, R.identity()); //=> [0, 1, 2, 3, 4]\n * @dataFirst\n * @category Array\n */\nexport function times<T, N extends number>(\n count: N,\n fn: (index: number) => T,\n): TimesArray<T, N>;\n\n/**\n * Calls an input function `n` times, returning an array containing the results\n * of those function calls.\n *\n * `fn` is passed one argument: The current value of `n`, which begins at `0`\n * and is gradually incremented to `n - 1`.\n *\n * @param fn - The function to invoke. Passed one argument, the current value of\n * `n`.\n * @returns An array containing the return values of all calls to `fn`.\n * @signature\n * R.times(fn)(count)\n * @example\n * R.times(R.identity())(5); //=> [0, 1, 2, 3, 4]\n * @dataLast\n * @category Array\n */\nexport function times<T>(\n fn: (index: number) => T,\n): <N extends number>(count: N) => TimesArray<T, N>;\n\nexport function times(...args: ReadonlyArray<unknown>): unknown {\n return purry(timesImplementation, args);\n}\n\nfunction timesImplementation<T>(\n count: number,\n fn: (index: number) => T,\n): Array<T> {\n if (count < 1) {\n // We prefer to return trivial results on trivial inputs vs throwing errors.\n return [];\n }\n\n // Non-integer numbers would cause `new Array` to throw, but it makes more\n // sense to simply round them down to the nearest integer instead; but\n // rounding has some performance implications so we only do it when we have to\n const length = Number.isInteger(count) ? count : Math.floor(count);\n\n // eslint-disable-next-line unicorn/no-new-array -- This is the most efficient way to create the array, check out the benchmarks in the PR that added this comment.\n const res = new Array<T>(length);\n\n for (let i = 0; i < length; i++) {\n res[i] = fn(i);\n }\n\n return res;\n}\n"],"mappings":"wCA4EA,SAAgB,EAAM,GAAG,EAAuC,CAC9D,OAAOA,EAAAA,EAAM,EAAqB,EAAK,CAGzC,SAAS,EACP,EACA,EACU,CACV,GAAI,EAAQ,EAEV,MAAO,EAAE,CAMX,IAAM,EAAS,OAAO,UAAU,EAAM,CAAG,EAAQ,KAAK,MAAM,EAAM,CAG5D,EAAU,MAAS,EAAO,CAEhC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,IAC1B,EAAI,GAAK,EAAG,EAAE,CAGhB,OAAO"}