01 · Problem
Wofür braucht man das?
Konfigurationen und Snapshots müssen häufig zeigen, welche Schlüssel hinzugefügt, entfernt oder verändert wurden.
02 · Denkmodell
Das mentale Modell
Ein Diff ist eine Menge adressierbarer Änderungen mit before und after. Die Vergleichstiefe und Gleichheitssemantik müssen Teil des Vertrags sein.
Berechnet gerichtete Array-Differenzen und flache Änderungen eigener Objektschlüssel ohne globale Mutation. Objektwerte werden per Identität verglichen; tiefer Strukturvergleich liegt außerhalb des Kerns.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Vereinigung aller eigenen Schlüssel beider Objekte bilden.
- Werte mit einer festgelegten Gleichheitsfunktion vergleichen.
- Nur abweichende Paare als before/after erfassen.
- Array-Differenz über ein Set der ausgeschlossenen Werte berechnen.
04 · Bauteile
Die entscheidenden Verträge
arrayDifference(left, right)Liefert linke Werte, die rechts fehlen.objectDifference(left, right)Liefert geänderte eigene Schlüssel als Alt/Neu-Tupel.05 · Selbst bauen
Selbst implementieren
Pure Funktionen vermeiden Namenskollisionen, enumerable Prototype-Properties und überraschende Seiteneffekte beim Import.
- Nimm beide Werte explizit als Parameter statt native Prototypen zu patchen.
- Benutze Object.keys und Object.is für ein klares flaches Diff.
- Behandle Deep-Diff, Array-Mengenlogik und Patch-Erzeugung als getrennte Erweiterungen.
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 · Verifizieren
Was solltest du testen?
- Hinzugefügte, entfernte und auf undefined gesetzte Keys bleiben unterscheidbar.
- NaN, -0 und Referenzobjekte folgen der dokumentierten Gleichheitssemantik.
- Der Import verändert weder Array.prototype noch Object und Eingaben bleiben unverändert.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Hinzugefügte, entfernte und auf undefined gesetzte Keys bleiben unterscheidbar.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- Ein flaches Diff ist schnell, erkennt aber Änderungen innerhalb verschachtelter Objekte nicht.
- Deep-Diffs benötigen Zyklenerkennung und eine definierte Behandlung von Map, Set und Klasseninstanzen.
Objektwerte werden per Identität verglichen; tiefer Strukturvergleich liegt außerhalb des Kerns.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/complex-compare/examples/basic.ts