Skip to content
Version

keyBy

The keyBy utility indexes an array into an object keyed by a property or selector function. When multiple items share the same key, the last one wins.

Source Code

View Source Code
ts
import type { Selector } from '../types';

import { assert } from '../function/assert';
import { IS_ARRAY_ERROR_MSG, isArray } from '../typed/isArray';

/**
 * Creates an object keyed by a property or selector function. When multiple
 * items share the same key, the last one wins.
 *
 * @example
 * ```ts
 * const data = [{ a: 'x', v: 1 }, { a: 'y', v: 2 }, { a: 'x', v: 3 }];
 * keyBy(data, 'a') // { x: { a: 'x', v: 3 }, y: { a: 'y', v: 2 } }
 * keyBy(data, item => item.a) // same result
 * ```
 *
 * @param array - The array to index.
 * @param selector - A property key or a function returning the key for each element.
 * @returns A record mapping each key to the corresponding element.
 *
 * @throws {TypeError} If the provided array is not an array.
 */
export function keyBy<T>(array: T[], selector: Selector<T>): Record<string, T> {
  assert(isArray(array), IS_ARRAY_ERROR_MSG, { args: { array }, type: TypeError });

  const result: Record<string, T> = {};
  const getKey = typeof selector === 'function' ? selector : (item: T) => item[selector];

  for (const item of array) {
    const key = String(getKey(item));

    result[key] = item;
  }

  return result;
}

Features

  • Property shorthand: Pass a string key for simple property-based indexing.
  • Custom selector: Pass a function for computed keys.
  • Last-wins deduplication: Duplicate keys overwrite earlier entries.

API

ts
function keyBy<T>(array: T[], selector: Selector<T>): Record<string, T>;

Parameters

  • array: The array to index.
  • selector: A property key string or a function (item: T) => string | number that returns the key for each element.

Returns

  • A Record<string, T> mapping each key to its corresponding element.

Throws

  • TypeError: If the first argument is not an array.

Examples

Index by Property Key

ts
import { keyBy } from '@vielzeug/toolkit';

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' },
];

keyBy(users, 'id');
// { '1': { id: 1, name: 'Alice' }, '2': { id: 2, name: 'Bob' }, '3': { id: 3, name: 'Charlie' } }

Index with Selector Function

ts
import { keyBy } from '@vielzeug/toolkit';

const products = [
  { sku: 'A-1', name: 'Widget', price: 9.99 },
  { sku: 'B-2', name: 'Gadget', price: 19.99 },
];

const bySku = keyBy(products, (p) => p.sku);
// { 'A-1': { sku: 'A-1', ... }, 'B-2': { sku: 'B-2', ... } }

// Fast O(1) lookup
bySku['A-1'].name; // 'Widget'

Duplicate Keys (Last Wins)

ts
import { keyBy } from '@vielzeug/toolkit';

const data = [
  { a: 'x', v: 1 },
  { a: 'y', v: 2 },
  { a: 'x', v: 3 }, // overwrites first
];

keyBy(data, 'a');
// { x: { a: 'x', v: 3 }, y: { a: 'y', v: 2 } }

See Also

  • group: Group into arrays of matching items instead of single entries.
  • select: Filter elements by a predicate.