Skip to main content

groupBy

groupBy() function

Splits Iterable/AsyncIterable into sets, grouped by the result of running each value through f.

Signature:
declare function groupBy<A extends Key>(f: (a: A) => A, iterable: Iterable<A>): {
[K in A]: K[];
};

declare function groupBy<A, B extends Key>(f: (a: A) => B, iterable: Iterable<A>): {
[K in B]: A[];
};

declare function groupBy<A extends Key>(f: (a: A) => A | Promise<A>, iterable: AsyncIterable<A>): Promise<{
[K in A]: K[];
}>;

declare function groupBy<A, B extends Key>(f: (a: A) => B | Promise<B>, iterable: AsyncIterable<A>): Promise<{
[K in B]: A[];
}>;

declare function groupBy<A extends Key, B extends Iterable<A> | AsyncIterable<A>>(f: (a: A) => A | Promise<A>): (iterable: B) => ReturnValueType<B, {
[K in A]: K[];
}>;

declare function groupBy<A extends object, B extends Key & A[keyof A]>(f: (a: A) => B, iterable: Iterable<A>): {
[K in B]: (A & {
[K2 in GetKeyOf<A, B>]: K;
})[];
};

declare function groupBy<A extends object, B extends Key & A[keyof A]>(f: (a: A) => B | Promise<B>, iterable: AsyncIterable<A>): Promise<{
[K in B]: (A & {
[K2 in GetKeyOf<A, B>]: K;
})[];
}>;

declare function groupBy<A extends Iterable<unknown> | AsyncIterable<unknown>, B extends Key>(f: (a: IterableInfer<A>) => B | Promise<B>): (iterable: A) => ReturnValueType<A, {
[K in B]: IterableInfer<A>[];
}>;

declare function groupBy<I extends Iterable<unknown> | AsyncIterable<unknown>, F extends (a: IterableInfer<I>) => any>(f: F): (iterable: I) => ReturnValueType<I, Equals<Awaited<ReturnType<F>>, IterableInfer<I>> extends 1 ? {
[key1 in Awaited<ReturnType<F>>]: key1[];
} : {
[key1 in Awaited<ReturnType<F>>]: (IterableInfer<I> & {
[key2 in GetKeyOf<Cast<IterableInfer<I>, object>, key1>]: key1;
})[];
}>;

Example

const given = [
{ category: "clothes", desc: "good" },
{ category: "pants", desc: "bad" },
{ category: "shoes", desc: "not bad" },
{ category: "shoes", desc: "great" },
{ category: "pants", desc: "good" },
];

groupBy((a) => a.category, given);
// {
// clothes: [{ category: "clothes", desc: "good" }],
// pants: [
// { category: "pants", desc: "bad" },
// { category: "pants", desc: "good" },
// ],
// shoes: [
// { category: "shoes", desc: "not bad" },
// { category: "shoes", desc: "great" },
// ],
// };

Try It