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.
Option, Result, Konstruktoren, Guards und match sind vollständig intern und werden nicht exportiert. Übliche Kombinatoren fehlen; der Matcher mischt Option- und Result-Zweige.
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
Option = Some | None (intern)
Explizite Anwesenheit eines Werts.
Result = Ok | Err (intern)
Expliziter Erfolg oder fachlicher Fehler.
isSome / isOk / match (intern)
Type Guards und Pattern-Matching-Helfer ohne Package-Export.
05 · Build it yourself
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 du testen solltest
- 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.
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.
Das vorhandene Modul zeigt die Kernidee, besitzt aber derzeit keine öffentliche API.
08 · Weiterdenken