01 · Problem
Wofür braucht man das?
null, undefined und Exceptions verstecken alternative Pfade. Option und Result machen diese Pfade zu sichtbaren Varianten im Typ.
02 · Denkmodell
Das mentale Modell
Jeder Wert trägt einen eindeutigen Tag. Consumer müssen vor dem Zugriff die Variante prüfen oder alle Varianten durch einen Matcher behandeln.
Exportiert markierte Option- und Result-Werte, Guards und Pattern Matching. Hüllen sind flach eingefroren; Fehlerfang und höhere Kombinatoren bleiben explizite Erweiterungen.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Erfolg, Fehler oder Abwesenheit als unveränderliche getaggte Variante erzeugen.
- Mit dem Tag verengen statt Felder oder Truthiness zu erraten.
- Transformationen nur auf der passenden Erfolgsvariante anwenden.
- Am Systemrand exhaustiv in Ausgabe, HTTP-Status oder Exception übersetzen.
04 · Bauteile
Die entscheidenden Verträge
Some / None / Ok / ErrErzeugt unveränderliche markierte Hüllen.isSome / isNone / isOk / isErr / matchVerengt und verarbeitet die jeweiligen Varianten.05 · Selbst bauen
Selbst implementieren
Discriminated Unions benötigen kaum Runtime-Code; die Qualität entsteht aus präzisen Kombinatoren und exhaustiven Switches.
- Definiere separate Tags und Payload-Felder für jede Variante.
- Baue kleine Konstruktoren sowie map und flatMap für Erfolgspfade.
- Nutze never-Checks, damit neue Varianten Compilerfehler an unvollständigen Matchern erzeugen.
type Result<T, E> =
| { tag: "ok"; value: T }
| { tag: "err"; error: E };
const ok = <T>(value: T): Result<T, never> => ({ tag: "ok", value });
const err = <E>(error: E): Result<never, E> => ({ tag: "err", error });
function map<A, B, E>(result: Result<A, E>, fn: (value: A) => B): Result<B, E> {
return result.tag === "ok" ? ok(fn(result.value)) : result;
}06 · Verifizieren
Was solltest du testen?
- map verändert ausschließlich Ok/Some und lässt Err/None unverändert.
- flatMap propagiert den ersten Fehler ohne den nächsten Schritt auszuführen.
- Exhaustive Matcher werden typseitig gegen neue Varianten abgesichert.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
map verändert ausschließlich Ok/Some und lässt Err/None unverändert.
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
- Result-Werte müssen konsequent behandelt werden; gemischte Exception- und Result-Semantik wird schnell unübersichtlich.
- Zu viele generische Kombinatoren können TypeScript-Inferenz und Fehlermeldungen verschlechtern.
Hüllen sind flach eingefroren; Fehlerfang und höhere Kombinatoren bleiben explizite Erweiterungen.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/functional/examples/basic.ts