import { ConditionalKeys, AllUnionFields, IfNever, Merge, And } from 'type-fest';
import { A as ArrayRequiredPrefix } from './ArrayRequiredPrefix-BtGBxz8-.cjs';
import { B as BoundedPartial } from './BoundedPartial-DBlvtqlX.cjs';
import { F as FilteredArray } from './FilteredArray-BV8mm6Do.cjs';
import { I as IterableContainer } from './IterableContainer-CtfinwiH.cjs';
import { T as TupleParts } from './TupleParts-Ci1vY__a.cjs';
import './CoercedArray-DRz3tqda.cjs';
import './RemedaTypeError-BIoNlKC-.cjs';
import './ClampedIntegerSubtract-DdO1KLSt.cjs';
import './IfBoundedRecord-WIX9x_oz.cjs';

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 };
