GitHub
teilweisepackages/ts-error/src

TS Error

@ralphschuler/ts-error

Normalisiert unbekannte Throw-Werte und bildet fehlschlagende Aufrufe als typisiertes Result ab.

errorsresultnormalization

01 · Problem

Wofür braucht man das?

JavaScript darf beliebige Werte werfen; Grenzen zwischen Bibliotheken, Workern oder JSON verlieren dadurch Namen, Ursache und zuverlässige Typen.

02 · Denkmodell

Das mentale Modell

Am Systemrand wird unknown einmal in eine serialisierbare Fehlerform überführt. Intern transportiert ein discriminated union Erfolg oder Fehler explizit.

Im Repository

NormalizedError, NoThrowResult, isError, toNormalizedError, noThrow und aggregateErrors werden exportiert. Die Normalform verlangt stets einen Stack, noThrow erkennt nur native Promises und Umgebungslogik greift auf process.env zu; ein Error als legitimer Rückgabewert bleibt mehrdeutig.

03 · Kontrollfluss

Was passiert in welcher Reihenfolge?

  1. Synchronen Aufruf oder Promise in try/catch beziehungsweise await einschließen.
  2. Gefangenen unknown-Wert ohne weitere Throws in eine sichere Struktur umwandeln.
  3. Erfolg und Fehler über ein eindeutiges ok-Feld unterscheiden.
  4. An Prozessgrenzen nur JSON-sichere Felder übertragen und Ursachen begrenzen.

04 · Bauteile

Die entscheidenden Verträge

NormalizedError Einheitliche Error-Unterklasse für unbekannte Fehlerwerte.
noThrow Wandelt synchrones oder asynchrones Werfen in ein Result um.
toNormalizedError / isError Normalisiert unknown und erkennt Error-artige Werte.
aggregateErrors Fasst mehrere Fehler zu einer gemeinsamen Meldung zusammen.

05 · Build it yourself

Selbst implementieren

Ein explizites Result vermeidet die Mehrdeutigkeit zwischen Rückgabewert und Fehler.

  1. Result als Union mit ok: true oder ok: false definieren.
  2. unknown über instanceof und sichere String-Konvertierung normalisieren.
  3. Async-Aufrufe immer mit await im selben try-Block ausführen.
minimal.ts · unabhängig vom Package
type Result<T> =
  | { ok: true; value: T }
  | { ok: false; error: { name: string; message: string; stack?: string } };

async function capture<T>(run: () => T | PromiseLike<T>): Promise<Result<T>> {
  try { return { ok: true, value: await run() }; }
  catch (value) {
    const error = value instanceof Error ? value : new Error(String(value));
    return { ok: false, error: { name: error.name, message: error.message, stack: error.stack } };
  }
}

06 · Verifizieren

Was du testen solltest

  • Error, String, null und ein Objekt mit werfender toString-Methode werden ohne Folgefehler normalisiert.
  • Thenables und native Promises liefern dieselbe Result-Form.
  • Ein regulär zurückgegebener Error bleibt durch ok: true eindeutig ein Wert.

07 · Grenzen

Kompromisse und Stolperfallen

  • Result macht Fehler im Typ sichtbar, erfordert aber explizites Branching an jedem Aufruf.
  • Stacks helfen beim Debugging, können jedoch Pfade oder andere interne Daten verraten.
  • Serialisierbare Fehler verlieren Prototyp und nicht standardisierte Eigenschaften.
Wichtig

Fehlernormalisierung darf selbst niemals werfen. Schütze deshalb auch String-Konvertierung und cause-Rekursion.

08 · Weiterdenken

Quellcode und Nachbarn

Originalcode auf GitHub ansehen