UNPKG

remeda

Version:

A utility library for JavaScript and Typescript.

93 lines (90 loc) 4.65 kB
import { ConditionalKeys, AllUnionFields, IfNever, Merge, And } from 'type-fest'; import { A as ArrayRequiredPrefix } from './ArrayRequiredPrefix-BfmKgW23.js'; import { B as BoundedPartial } from './BoundedPartial-D9pXZQqa.js'; import { F as FilteredArray } from './FilteredArray-0g05hoCh.js'; import { I as IterableContainer } from './IterableContainer-CtfinwiH.js'; import { T as TupleParts } from './TupleParts-BeowYtF7.js'; import './CoercedArray-DRz3tqda.js'; import './RemedaTypeError-BIoNlKC-.js'; import './ClampedIntegerSubtract-DdO1KLSt.js'; import './IsBoundedRecord-CeHuKZ6O.js'; type GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>> = T extends unknown ? FixEmptyObject<EnsureValuesAreNonEmpty<{ [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>; }>> : never; type GroupableProps<T extends IterableContainer> = ConditionalKeys<ItemsSuperObject<T>, PropertyKey | undefined>; type AllPropValues<T extends IterableContainer, Prop extends GroupableProps<T>> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>; type ItemsSuperObject<T extends IterableContainer> = AllUnionFields<Exclude<T[number], undefined>>; type FixEmptyObject<T> = IfNever<keyof T, Record<PropertyKey, never>, T>; type EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>> = Merge<T, BoundedPartial<{ [P in keyof T as IsPossiblyEmpty<T[P]> extends true ? P : never]: ArrayRequiredPrefix<T[P], 1>; }>>; type IsPossiblyEmpty<T extends IterableContainer> = And<IsEmpty<TupleParts<T>["required"]>, IsEmpty<TupleParts<T>["suffix"]>>; type IsEmpty<T> = T extends readonly [] ? true : false; /** * Groups the elements of an array of objects based on the values of a * specified property of those objects. The result would contain a property for * each unique value of the specific property, with it's value being the input * array filtered to only items that have that property set to that value. * For any object where the property is missing, or if it's value is * `undefined` the item would be filtered out. * * The grouping property is enforced at the type level to exist in at least one * item and to never have a value that cannot be used as an object key (e.g. it * must be `PropertyKey | undefined`). * * The resulting arrays are filtered with the prop and it's value as a * type-guard, effectively narrowing the items in each output arrays. This * means that when the grouping property is the discriminator of a * discriminated union type each output array would contain just the subtype for * that value. * * If you need more control over the grouping you should use `groupBy` instead. * * @param data - The items to group. * @param prop - The property name to group by. * @signature * R.groupByProp(data, prop) * @example * const result = R.groupByProp( * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] } * [{ a: 'cat' }, { a: 'dog' }] as const, * 'a', * ); * @dataFirst * @category Array */ declare function groupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>(data: T, prop: Prop): GroupByProp<T, Prop>; /** * Groups the elements of an array of objects based on the values of a * specified property of those objects. The result would contain a property for * each unique value of the specific property, with it's value being the input * array filtered to only items that have that property set to that value. * For any object where the property is missing, or if it's value is * `undefined` the item would be filtered out. * * The grouping property is enforced at the type level to exist in at least one * item and to never have a value that cannot be used as an object key (e.g. it * must be `PropertyKey | undefined`). * * The resulting arrays are filtered with the prop and it's value as a * type-guard, effectively narrowing the items in each output arrays. This * means that when the grouping property is the discriminator of a * discriminated union type each output array would contain just the subtype for * that value. * * If you need more control over the grouping you should use `groupBy` instead. * * @param prop - The property name to group by. * @signature * R.groupByProp(prop)(data); * @example * const result = R.pipe( * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] } * [{ a: 'cat' }, { a: 'dog' }] as const, * R.groupByProp('a'), * ); * @dataLast * @category Array */ declare function groupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>(prop: Prop): (data: T) => GroupByProp<T, Prop>; export { groupByProp };