API reference@evolu/commonObject › createMutableRecord

Call Signature

function createMutableRecord<K, V>(): Record<K, V>;

Defined in: packages/common/src/Object.ts:344

Creates a mutable Record.

Use it to build a Record locally through mutation, avoiding repeated object spreads. Keep mutation scoped to the constructing function, and treat the completed Record as immutable after it leaves that scope. When a source is provided, its own enumerable properties are shallow-copied. Inherited and non-enumerable properties are not copied.

The Record is created with Object.create(null), so any string can be used as a key while it is being built. Missing keys such as toString and constructor do not resolve to inherited values, and assigning __proto__ creates an own data property instead of changing the prototype.

The null prototype makes dynamic construction safer, but it does not have to be preserved. Spreading the completed Record into an ordinary object is supported. Use getOwnProp when a lookup must read only own properties.

For immutable empty application data, defaults, or placeholders, use emptyRecord.

Example

import { assertEqual, createMutableRecord } from "@evolu/common";

const createValuesByKey = (
  entries: ReadonlyArray<readonly [string, number]>,
): Readonly<Record<string, number>> => {
  const valuesByKey = createMutableRecord<string, number>();

  for (const [key, value] of entries) {
    valuesByKey[key] = value;
  }

  return valuesByKey;
};

assertEqual(
  createValuesByKey([
    ["a", 1],
    ["b", 2],
  ]),
  { a: 1, b: 2 },
);

Note that TypeScript does not model an object's runtime prototype. A plain TypeScript Record exposes Object.prototype members even when the runtime object has a null prototype:

import { assertErr, assertTrue, trySync } from "@evolu/common";

const values = Object.create(null) as Record<string, number>;

// TypeScript accepts the call, but `toString` is undefined at runtime.
// oxlint-disable-next-line typescript/no-base-to-string -- Intentionally calls a method missing from the null-prototype value.
const result = trySync(() => values.toString());
assertErr(result);
assertTrue(result.error instanceof TypeError);

createMutableRecord uses the same TypeScript Record representation.

import {
  assertErr,
  assertTrue,
  createMutableRecord,
  trySync,
} from "@evolu/common";

const values = createMutableRecord<string, number>();

// TypeScript accepts the call, but `toString` is undefined at runtime.
// oxlint-disable-next-line typescript/no-base-to-string -- Intentionally calls a method missing from the null-prototype value.
const result = trySync(() => values.toString());
assertErr(result);
assertTrue(result.error instanceof TypeError);

In other words, treat the returned object as string-keyed data rather than calling inherited object methods through it.

Call Signature

function createMutableRecord<T>(source: T): {
  -readonly [K in string | number | symbol]: T[K];
};

Defined in: packages/common/src/Object.ts:350

Creates a mutable null-prototype copy of an object.