remeda
Version:
A utility library for JavaScript and Typescript.
71 lines (70 loc) • 4.23 kB
TypeScript
import { IterableContainer } from "./IterableContainer-B2PfkIAC.js";
import { NTuple } from "./NTuple-sy5afYiG.js";
import { PartialArray } from "./PartialArray-CGJOFu0O.js";
import { TupleParts } from "./TupleParts-Dc0oO91w.js";
import { CoercedArray } from "./CoercedArray-Cm2pzy31.js";
import { FixedLengthArray, IsEqual, IsNever, NonNegativeInteger, Or, Writable } from "type-fest";
//#region src/sample.d.ts
type Sampled<T extends IterableContainer, N extends number> = Or<IsEqual<N, 0>, IsEqual<T["length"], 0>> extends true ? [] : IsNever<NonNegativeInteger<N>> extends true ? SampledPrimitive<T> : IsLongerThan<T, N> extends true ? SampledLiteral<T, N> : Writable<T>;
/**
* When N is not a non-negative integer **literal** we can't use it in our
* reconstructing logic so we fallback to a simpler definition of the output of
* sample, which is any sub-tuple shape of T, of **any length**.
*/
type SampledPrimitive<T extends IterableContainer> = [...FixedSubTuples<TupleParts<T>["required"]>, ...PartialArray<FixedSubTuples<TupleParts<T>["optional"]>>, ...CoercedArray<TupleParts<T>["item"]>, ...FixedSubTuples<TupleParts<T>["suffix"]>];
/**
* Knowing N is a non-negative literal integer we can construct all sub-tuples
* of T that are exactly N elements long.
*/
type SampledLiteral<T extends IterableContainer, N extends number> = Extract<FixedSubTuples<[...TupleParts<T>["required"], ...(IsNever<TupleParts<T>["item"]> extends true ? [] : NTuple<TupleParts<T>["item"], N>), ...TupleParts<T>["suffix"]]>, FixedLengthArray<unknown, N>> | SubSampled<TupleParts<T>["required"], TupleParts<T>["item"], TupleParts<T>["suffix"], N>;
type SubSampled<Prefix extends ReadonlyArray<unknown>, Item, Suffix extends ReadonlyArray<unknown>, N extends number> = IsLongerThan<[...Prefix, ...Suffix], N> extends true ? never : [...Prefix, ...Suffix]["length"] extends N ? never : [...Prefix, ...Suffix] | SubSampled<[...Prefix, Item], Item, Suffix, N>;
type IsLongerThan<T extends ReadonlyArray<unknown>, N extends number> = IsEqual<T[N], undefined> extends true ? false : true;
type FixedSubTuples<T> = T extends readonly [infer Head, ...infer Rest] ?
// For each element we either take it or skip it, and recurse over the rest.
FixedSubTuples<Rest> | [Head, ...FixedSubTuples<Rest>] : [];
/**
* Returns a random subset of size `sampleSize` from `array`.
*
* Maintains and infers most of the typing information that could be passed
* along to the output. This means that when using tuples, the output will be
* a tuple too, and when using literals, those literals would be preserved.
*
* The items in the result are kept in the same order as they are in the input.
* If you need to get a shuffled response you can pipe the shuffle function
* after this one.
*
* @param data - The array.
* @param sampleSize - The number of elements to take.
* @signature
* R.sample(array, sampleSize)
* @example
* R.sample(["hello", "world"], 1); // => ["hello"] // typed string[]
* R.sample(["hello", "world"] as const, 1); // => ["world"] // typed ["hello" | "world"]
* @dataFirst
* @category Array
*/
declare function sample<const T extends IterableContainer, N extends number>(data: T, sampleSize: N): Sampled<T, N>;
/**
* Returns a random subset of size `sampleSize` from `array`.
*
* Maintains and infers most of the typing information that could be passed
* along to the output. This means that when using tuples, the output will be
* a tuple too, and when using literals, those literals would be preserved.
*
* The items in the result are kept in the same order as they are in the input.
* If you need to get a shuffled response you can pipe the shuffle function
* after this one.
*
* @param sampleSize - The number of elements to take.
* @signature
* R.sample(sampleSize)(array)
* @example
* R.sample(1)(["hello", "world"]); // => ["hello"] // typed string[]
* R.sample(1)(["hello", "world"] as const); // => ["world"] // typed ["hello" | "world"]
* @dataLast
* @category Array
*/
declare function sample<const T extends IterableContainer, N extends number>(sampleSize: N): (data: T) => Sampled<T, N>;
//#endregion
export { sample };
//# sourceMappingURL=sample-CD400rJm.d.ts.map