Skip to main content

indexBy

indexBy() function

Given f that generates a key, turns a list of objects into an object indexing the objects by the given key. Note that if multiple objects generate the same value for the indexing key only the last value will be included in the generated object.

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

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

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

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

declare function indexBy<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 indexBy<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 indexBy<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 indexBy<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" },
];

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

Try It