DeutschGitHub
partialpackages/complex-compare/src

Complex Compare

@ralphschuler/complex-compare

Computes directional array differences and shallow own-key object changes without global mutation.

diffobjectspure functions

01 · Problem

What is it for?

Global prototype extensions affect unrelated code and hide the direction of a comparison.

02 · Mental model

How should you think about it?

Return explicit left-to-right differences. A shallow change record contains the previous and next value for each changed own key.

In this repository

Computes directional array differences and shallow own-key object changes without global mutation. Object values are compared by identity; nested structural comparison is deliberately outside the core.

03 · Control flow

What happens in which order?

  1. Collect candidate own keys or values.
  2. Compare membership or Object.is values.
  3. Record removed, added and changed entries.
  4. Return the result without mutating either input.

04 · Building blocks

The important contracts

arrayDifference(left, right)Return left values absent on the right.
objectDifference(left, right)Return changed own keys as old/new value tuples.

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. Collect candidate own keys or values.
  2. Compare membership or Object.is values.
  3. Record removed, added and changed entries.
  4. Return the result without mutating either input.
Concept sketch · may reference omitted helpers
function objectDiff(
  left: Record<string, unknown>,
  right: Record<string, unknown>,
) {
  const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
  const changes = new Map<string, { before: unknown; after: unknown }>();
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      changes.set(key, { before: left[key], after: right[key] });
    }
  }
  return changes;
}

06 · Verify

What should you test?

  • Test added and removed keys including undefined.
  • Test directional array differences.
  • Verify imports leave global prototypes unchanged.

Try it yourself

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

Test added and removed keys including undefined.

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

  • Nested objects are compared by identity.
  • Array difference retains duplicates from the left.
  • Own-key presence and an undefined value are distinct.
Important

Object values are compared by identity; nested structural comparison is deliberately outside the core.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/complex-compare/examples/basic.ts