keyBy()
keyBy<
T,K>(array,iteratee):Partial<Record<K,T>>
Creates an object composed of keys generated from the results of running each element through iteratee.
In case of duplicate keys, the last value wins.
Type Parametersโ
T: Tโ
The type of elements in the array.
K: K extends PropertyKeyโ
The type of the key returned by the iteratee.
Parametersโ
array: readonly T[]โ
The array to iterate over.
iteratee: (value) => Kโ
A function that returns the key for each element.
Returns: Partial<Record<K, T>>โ
An object with keys mapping to elements.
Sinceโ
2.0.0
Performanceโ
O(n) time & space.
Also known asโ
indexBy (Remeda, Ramda) ยท keyBy (Lodash, es-toolkit) ยท objectify (Radashi) ยท โ (Effect, Modern Dash, Antfu)
Exampleโ
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 3, name: 'Bob' }
];
keyBy(users, (u) => u.id);
// => { 1: { id: 1, name: 'John' }, 2: { id: 2, name: 'Jane' }, 3: { id: 3, name: 'Bob' } }
keyBy(['apple', 'banana', 'cherry'], (s) => s[0]);
// => { a: 'apple', b: 'banana', c: 'cherry' }
How it works?โ
Creates an object where each element is stored under a computed key. Last value wins for duplicate keys.
keyBy vs groupByโ
| Function | Duplicate keys | Returns |
|---|---|---|
keyBy | Last wins | { key: T } |
groupBy | All kept | { key: T[] } |
Use Casesโ
Create lookup tables for instant access by ID ๐โ
Transform an array into an object indexed by unique identifier. Perfect for normalizing API responses, caching entities, or quick O(1) lookups.
const users = [
{ id: "u1", name: "Alice", role: "admin" },
{ id: "u2", name: "Bob", role: "user" },
{ id: "u3", name: "Charlie", role: "user" },
];
const usersById = keyBy(users, (u) => u.id);
// => {
// u1: { id: "u1", name: "Alice", role: "admin" },
// u2: { id: "u2", name: "Bob", role: "user" },
// u3: { id: "u3", name: "Charlie", role: "user" }
// }
const alice = usersById["u1"];
// => { id: "u1", name: "Alice", role: "admin" }
Index configuration objects by key property ๐โ
Map settings or config items for quick retrieval by name or code. Ideal for feature flags, locale settings, or environment configurations.
const features = [
{ code: "DARK_MODE", enabled: true, description: "Enable dark theme" },
{ code: "BETA_UI", enabled: false, description: "New UI experiment" },
{ code: "ANALYTICS", enabled: true, description: "Track user events" },
];
const featureFlags = keyBy(features, (f) => f.code);
// => {
// DARK_MODE: { code: "DARK_MODE", enabled: true, ... },
// BETA_UI: { code: "BETA_UI", enabled: false, ... },
// ANALYTICS: { code: "ANALYTICS", enabled: true, ... }
// }
if (featureFlags["DARK_MODE"]?.enabled) {
applyDarkTheme();
}
Map relational data for join-like operationsโ
Index related entities to efficiently merge data from multiple sources. Useful for combining API responses, denormalizing data, or building relationships.
const orders = [
{ orderId: 1, productId: "p1", quantity: 2 },
{ orderId: 2, productId: "p3", quantity: 1 },
{ orderId: 3, productId: "p2", quantity: 5 },
];
const products = [
{ sku: "p1", name: "Keyboard", price: 79 },
{ sku: "p2", name: "Mouse", price: 29 },
{ sku: "p3", name: "Monitor", price: 299 },
];
const productsBySku = keyBy(products, (p) => p.sku);
const enrichedOrders = orders.map((order) => ({
...order,
product: productsBySku[order.productId],
total: (productsBySku[order.productId]?.price ?? 0) * order.quantity,
}));
Normalize API response for a Redux/Zustand store ๐โ
Convert an array of entities into a normalized { byId, allIds } structure for state management.
The most common real-world pattern for keyBy in any app using Redux, Zustand, or similar stores.
const apiResponse = [
{ id: "p1", title: "Build UI", status: "done" },
{ id: "p2", title: "Write tests", status: "in-progress" },
{ id: "p3", title: "Deploy", status: "todo" },
];
const normalized = {
byId: keyBy(apiResponse, (item) => item.id),
allIds: apiResponse.map((item) => item.id),
};
// normalized.byId["p2"] => { id: "p2", title: "Write tests", status: "in-progress" }
// normalized.allIds => ["p1", "p2", "p3"]
// Fast update without scanning the array
normalized.byId["p2"] = { ...normalized.byId["p2"], status: "done" };