01 · Problem
Wofür braucht man das?
Direkt geteilter Objektzustand verrät nicht, wer ihn wann verändert hat, und koppelt Leser, Schreiber sowie Seiteneffekte eng aneinander.
02 · Denkmodell
Das mentale Modell
Ein Store besitzt den Zustand. Schreiboperationen erzeugen eine neue Version und informieren nur Abonnenten des geänderten Schlüssels.
StateStore und createStateStore sind angelegt, der Root-Export ist aber leer. Der Proxy-get-Trap verdeckt eigene Methoden; Listener werden indirekt über das Setzen einer Funktion angelegt, während eine öffentliche, wieder abmeldbare Registrierung fehlt.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Initialzustand defensiv kopieren und nur über eine kleine Store-API zugänglich machen.
- Bei set alten und neuen Wert vergleichen und den Zustand aktualisieren.
- Passende Listener mit Wert, Vorwert und Schlüssel benachrichtigen.
- Eine unsubscribe-Funktion zurückgeben und Listener beim Aufräumen entfernen.
04 · Bauteile
Die entscheidenden Verträge
StateStore
Experimentelle Store-Klasse mit Proxy-basierter Oberfläche.
createStateStore
Erzeugt einen Store aus typisiertem Initialzustand.
Middleware / Interceptor
Typen für Transformation und Beobachtung von Schreibzugriffen.
05 · Build it yourself
Selbst implementieren
Eine explizite API ist leichter zu verstehen und zu testen als magische Proxy-Semantik.
- Zustand privat halten und Werte über get auslesen.
- Schreibzugriffe in set bündeln und unveränderte Werte überspringen.
- Subscriptions in Sets verwalten und immer eine unsubscribe-Funktion liefern.
class Store<S extends object> {
private listeners = new Set<(state: Readonly<S>) => void>();
constructor(private state: S) {}
get() { return this.state as Readonly<S>; }
set(update: Partial<S>) {
this.state = { ...this.state, ...update };
for (const listener of this.listeners) listener(this.state);
}
subscribe(listener: (state: Readonly<S>) => void) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
}06 · Verifizieren
Was du testen solltest
- set behält unberührte Schlüssel und veröffentlicht den neuen Snapshot.
- unsubscribe verhindert alle späteren Benachrichtigungen.
- Ein Listener darf sich während einer Benachrichtigung sicher abmelden.
07 · Grenzen
Kompromisse und Stolperfallen
- Snapshots sind nachvollziehbar, kopieren bei großen Objekten jedoch mehr Daten.
- Schlüsselbezogene Listener sparen Arbeit, vergrößern aber die API.
- Proxies wirken bequem, erschweren Debugging und kollidieren leicht mit Store-Methoden.
Veröffentliche niemals den intern mutierbaren Zustand; nutze Readonly-Sichten oder unveränderliche Snapshots.
08 · Weiterdenken