DeutschGitHub
partialpackages/better-map/src

Better Map

@ralphschuler/better-map

Updates, filters and merges Map entries with explicit missing-value behavior.

Mapcollectionsmerge

01 · Problem

What is it for?

Repeated get-transform-set code obscures missing values and conflict resolution.

02 · Mental model

How should you think about it?

Keep Map as the underlying structure and make mutation versus copying visible in each operation.

In this repository

Updates, filters and merges Map entries with explicit missing-value behavior. Values retain reference identity; callbacks are synchronous and can throw.

03 · Control flow

What happens in which order?

  1. Use has to distinguish absence from a stored undefined.
  2. Transform an existing value or choose an explicit default.
  3. Write the new value once.
  4. Resolve merge conflicts through a callback.

04 · Building blocks

The important contracts

updateTransform existing values or initialize missing entries.
filter / mergeFilter to a new map or mutate by merging.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Use has to distinguish absence from a stored undefined.
  2. Transform an existing value or choose an explicit default.
  3. Write the new value once.
  4. Resolve merge conflicts through a callback.
Concept sketch · may reference omitted helpers
class UpdatingMap<K, V> extends Map<K, V> {
  update(key: K, change: (value: V) => V, create: () => V): this {
    const next = this.has(key) ? change(this.get(key) as V) : create();
    this.set(key, next);
    return this;
  }

  select(predicate: (value: V, key: K) => boolean) {
    const result = new UpdatingMap<K, V>();
    for (const [key, value] of this) {
      if (predicate(value, key)) result.set(key, value);
    }
    return result;
  }
}

06 · Verify

What should you test?

  • Test stored undefined separately from a missing key.
  • Preserve explicit null and undefined defaults.
  • Verify filtering leaves the original unchanged.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

Test stored undefined separately from a missing key.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • Values are copied by reference.
  • Updater callbacks may throw.
  • Document which operations mutate the receiver.
Important

Values retain reference identity; callbacks are synchronous and can throw.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/better-map/examples/basic.ts