UNPKG

remeda

Version:

A utility library for JavaScript and Typescript.

1 lines 6.69 kB
{"version":3,"file":"drop.cjs","names":["purry","lazyIdentityEvaluator","SKIP_ITEM"],"sources":["../src/drop.ts"],"sourcesContent":["import type { IsInteger, IsNegative, Writable } from \"type-fest\";\nimport type { ClampedIntegerSubtract } from \"./internal/types/ClampedIntegerSubtract\";\nimport type { CoercedArray } from \"./internal/types/CoercedArray\";\nimport type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport type { LazyEvaluator } from \"./internal/types/LazyEvaluator\";\nimport type { PartialArray } from \"./internal/types/PartialArray\";\nimport type { TupleParts } from \"./internal/types/TupleParts\";\nimport { SKIP_ITEM, lazyIdentityEvaluator } from \"./internal/utilityEvaluators\";\nimport { purry } from \"./purry\";\n\ntype Drop<T extends IterableContainer, N extends number> =\n IsNegative<N> extends true\n ? // Negative numbers result in nothing being dropped, we return a shallow\n // clone of the array.\n Writable<T>\n : IsInteger<N> extends false\n ? // We can't compute accurate types for non-integer numbers so we\n // fallback to the \"legacy\" typing where we convert our output to a\n // simple array. This is also the case when N is not a literal value\n // (e.g. it is `number`).\n // TODO: We can improve this type by returning a union of all possible dropped shapes (e.g. the equivalent of Drop<T, 1> | Drop<T, 2> | Drop<T, 3> | ...).\n Array<T[number]>\n : ClampedIntegerSubtract<\n N,\n TupleParts<T>[\"required\"][\"length\"]\n > extends infer RemainingPrefix extends number\n ? RemainingPrefix extends 0\n ? // The drop will occur within the required part of the tuple, we\n // simply remove those elements from it and reconstruct the rest of\n // the tuple.\n [\n ...DropFixedTuple<TupleParts<T>[\"required\"], N>,\n ...PartialArray<TupleParts<T>[\"optional\"]>,\n ...CoercedArray<TupleParts<T>[\"item\"]>,\n ...TupleParts<T>[\"suffix\"],\n ]\n : ClampedIntegerSubtract<\n RemainingPrefix,\n TupleParts<T>[\"optional\"][\"length\"]\n > extends infer RemainingOptional extends number\n ? RemainingOptional extends 0\n ? // The drop will occur within the optional part of the tuple, we\n // completely remove the required part, remove enough elements\n // from the optional part, and reconstruct the rest of the\n // tuple.\n [\n ...PartialArray<\n DropFixedTuple<TupleParts<T>[\"optional\"], RemainingPrefix>\n >,\n ...CoercedArray<TupleParts<T>[\"item\"]>,\n ...TupleParts<T>[\"suffix\"],\n ]\n : // The drop will occur within the rest element or the suffix.\n // Because the suffix can contain any number of elements this\n // case adds more complexity as we need to consider all\n // possible (relevant) lengths. We start by considering the\n // case where there are enough elements within the rest\n // param; this means we still maintain the rest element as it\n // could contain even more elements, and we add the suffix\n // untouched.\n | [\n ...CoercedArray<TupleParts<T>[\"item\"]>,\n ...TupleParts<T>[\"suffix\"],\n ]\n // Additionally, we need to consider the case where the rest\n // element has up to the same number of elements as the\n // suffix; this will result in removing the rest element\n // entirely, and dropping elements from the suffix. We do this\n // for all possible values from 0 to N where N is the\n // remaining value after we handled the prefix. We can exclude\n // the 0 case because it is contained in the previous case.\n | Exclude<\n DropFixedTuple<\n TupleParts<T>[\"suffix\"],\n RemainingOptional,\n true /* IncludePrefixes */\n >,\n TupleParts<T>[\"suffix\"]\n >\n : never\n : never;\n\ntype DropFixedTuple<\n T,\n N,\n // This flag controls if we want a union of all possible prefixes, or just the\n // final tuple with all N items dropped.\n IncludePrefixes = false,\n Dropped extends Array<unknown> = [],\n> = Dropped[\"length\"] extends N\n ? T\n : T extends readonly [unknown, ...infer Rest]\n ?\n | DropFixedTuple<Rest, N, IncludePrefixes, [...Dropped, unknown]>\n | (true extends IncludePrefixes ? T : never)\n : [];\n\n/**\n * Removes first `n` elements from the `array`.\n *\n * @param array - The target array.\n * @param n - The number of elements to skip.\n * @signature\n * R.drop(array, n)\n * @example\n * R.drop([1, 2, 3, 4, 5], 2) // => [3, 4, 5]\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function drop<T extends IterableContainer, N extends number>(\n array: T,\n n: N,\n): Drop<T, N>;\n\n/**\n * Removes first `n` elements from the `array`.\n *\n * @param n - The number of elements to skip.\n * @signature\n * R.drop(n)(array)\n * @example\n * R.drop(2)([1, 2, 3, 4, 5]) // => [3, 4, 5]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function drop<N extends number>(\n n: N,\n): <T extends IterableContainer>(array: T) => Drop<T, N>;\n\nexport function drop(...args: ReadonlyArray<unknown>): unknown {\n return purry(dropImplementation, args, lazyImplementation);\n}\n\nconst dropImplementation = <T extends IterableContainer>(\n array: T,\n n: number,\n): Array<T[number]> => (n < 0 ? [...array] : array.slice(n));\n\nfunction lazyImplementation<T>(n: number): LazyEvaluator<T> {\n if (n <= 0) {\n return lazyIdentityEvaluator;\n }\n\n let left = n;\n return (value) => {\n if (left > 0) {\n left -= 1;\n return SKIP_ITEM;\n }\n return { done: false, hasNext: true, next: value };\n };\n}\n"],"mappings":"sFAmIA,SAAgB,EAAK,GAAG,EAAuC,CAC7D,OAAOA,EAAAA,EAAM,EAAoB,EAAM,EAAmB,CAG5D,MAAM,GACJ,EACA,IACsB,EAAI,EAAI,CAAC,GAAG,EAAM,CAAG,EAAM,MAAM,EAAE,CAE3D,SAAS,EAAsB,EAA6B,CAC1D,GAAI,GAAK,EACP,OAAOC,EAAAA,EAGT,IAAI,EAAO,EACX,MAAQ,IACF,EAAO,GACT,IACOC,EAAAA,GAEF,CAAE,KAAM,GAAO,QAAS,GAAM,KAAM,EAAO"}