remeda
Version:
A utility library for JavaScript and Typescript.
66 lines (65 loc) • 3.8 kB
TypeScript
import { IsUnion } from "./IsUnion-DOpuao5P.js";
import { TupleParts } from "./TupleParts-Dc0oO91w.js";
import { IsBounded, IsBoundedRecord } from "./IsBoundedRecord-ByJkcRpD.js";
import { EmptyObject, IsNever, KeysOfUnion, Writable } from "type-fest";
//#region src/pick.d.ts
type PickFromArray<T, Keys extends ReadonlyArray<KeysOfUnion<T>>> = T extends unknown ? Keys extends unknown ? IsNever<Extract<Keys[number], keyof T>> extends true ? EmptyObject : Writable<IsBoundedRecord<T> extends true ? PickBoundedFromArray<T, Keys> : PickUnbounded<T, Extract<Keys[number], keyof T>>> : never : never;
/**
* Bounded records have bounded keys and result in a bounded output. The only
* question left is whether to add the prop as-is, or make it optional. This
* can be determined by the part of the keys array the prop is defined in, and
* the way that element is defined: if the array contains a singular literal
* key in either the required prefix or the suffix, we know that prop should be
* picked as-is, otherwise, the key might not be present in the keys array so it
* can only be picked optionally.
*/
type PickBoundedFromArray<T, Keys extends ReadonlyArray<KeysOfUnion<T>>> = Pick<T, Extract<ItemsByUnion<TupleParts<Keys>["required"]>["singular"] | ItemsByUnion<TupleParts<Keys>["suffix"]>["singular"], keyof T>> & Partial<Pick<T, Extract<ItemsByUnion<TupleParts<Keys>["required"]>["union"] | TupleParts<Keys>["optional"][number] | TupleParts<Keys>["item"] | ItemsByUnion<TupleParts<Keys>["suffix"]>["union"], keyof T>>>;
/**
* We split the fixed tuple item types into **singular** props (e.g., `"a"`),
* and unions of several props (e.g., `"a" | "b"`).
*
* We assume that T is a fixed tuple (no optional or rest elements), and that
* all elements in it are bounded (as defined by `IsBounded`).
*/
type ItemsByUnion<T, Singular = never, Union = never> = T extends readonly [infer Head, ...infer Rest] ? IsUnion<Head> extends true ? ItemsByUnion<Rest, Singular, Union | Head> : ItemsByUnion<Rest, Singular | Head, Union> : {
singular: Singular;
union: Union;
};
/**
* The built-in `Pick` is weird when it comes to picking bounded keys from
* unbounded records. It reconstructs the output object regardless of the shape
* of the input: `Pick<Record<string, "world">, "hello">` results in the type
* `{ hello: "world" }`, but you'd expect it to be optional because we don't
* know if the record contains a `hello` prop or not!
*
* !Important: We assume T is unbounded and don't test for it!
*
* See: https://www.typescriptlang.org/play/?#code/PTAEE0HsFcHIBNQFMAeAHJBjALqAGqNpKAEZKigAGA3qABZIA2jkA-AFygBEA7pAE6N4XUAF9KAGlLRcAQ0ayAzgChsATwz5QAXlAAFAJaYA1gB4ASlgHxTi7PwMA7AOZTeAoVwB8bhs0jeANzKIBSgAHqsykA.
*/
type PickUnbounded<T, Keys extends keyof T> = IsBounded<Keys> extends true ? Partial<Pick<T, Keys>> : Pick<T, Keys>;
/**
* Creates an object composed of the picked `data` properties.
*
* @param keys - The property names.
* @signature R.pick([prop1, prop2])(object)
* @example
* R.pipe({ a: 1, b: 2, c: 3, d: 4 }, R.pick(['a', 'd'])) // => { a: 1, d: 4 }
* @dataLast
* @category Object
*/
declare function pick<T extends object, const Keys extends ReadonlyArray<KeysOfUnion<T>>>(keys: Keys): (data: T) => PickFromArray<T, Keys>;
/**
* Creates an object composed of the picked `data` properties.
*
* @param data - The target object.
* @param keys - The property names.
* @signature R.pick(object, [prop1, prop2])
* @example
* R.pick({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'd']) // => { a: 1, d: 4 }
* @dataFirst
* @category Object
*/
declare function pick<T extends object, const Keys extends ReadonlyArray<KeysOfUnion<T>>>(data: T, keys: Keys): PickFromArray<T, Keys>;
//#endregion
export { pick };
//# sourceMappingURL=pick-jpwOS5t8.d.ts.map