GitHub
Prototyppackages/state-store/src

State Store

@ralphschuler/state-store

Kapselt veränderbaren Anwendungszustand hinter get, set und gezielten Subscriptions.

storeproxysubscriptions

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.

Im Repository

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?

  1. Initialzustand defensiv kopieren und nur über eine kleine Store-API zugänglich machen.
  2. Bei set alten und neuen Wert vergleichen und den Zustand aktualisieren.
  3. Passende Listener mit Wert, Vorwert und Schlüssel benachrichtigen.
  4. 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.

  1. Zustand privat halten und Werte über get auslesen.
  2. Schreibzugriffe in set bündeln und unveränderte Werte überspringen.
  3. Subscriptions in Sets verwalten und immer eine unsubscribe-Funktion liefern.
minimal.ts · unabhängig vom Package
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.
Wichtig

Veröffentliche niemals den intern mutierbaren Zustand; nutze Readonly-Sichten oder unveränderliche Snapshots.

08 · Weiterdenken

Quellcode und Nachbarn

Originalcode auf GitHub ansehen