Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Fehlerbehandlung mit Typen in TypeScript

Fehlerbehandlung mit Typen

~16 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Unsere leiheAus()-Methode (Kapitel 14) gibt bisher nur boolean zurück – Erfolg oder Misserfolg, aber KEINE Information, WARUM etwas fehlgeschlagen ist. Dieses Kapitel zeigt zwei bessere Muster: eigene Error-Klassen und das "Result-Type"-Pattern.

Ein grundlegendes TypeScript-Problem: catch(error)

try {
  bibliothek.leiheAus('123');
} catch (error) {
  console.log(error.message); // Fehler! error hat den Typ 'unknown', NICHT 'Error'
}

In modernem TypeScript (seit Version 4.4, strict aktiviert) hat error in einem catch-Block standardmäßig den Typ unknown (Kapitel 4) – NICHT Error, weil JavaScript technisch erlaubt, ALLES zu werfen (throw 'ein String', throw 42 sind beide gültig). TypeScript ZWINGT Sie, das zu berücksichtigen.

try {
  bibliothek.leiheAus('123');
} catch (error) {
  if (error instanceof Error) { // Type Narrowing aus Kapitel 19!
    console.log(error.message); // ✓ jetzt erlaubt - error ist als Error erkannt
  } else {
    console.log('Unbekannter Fehler:', error);
  }
}

Eigene Error-Klassen

src/errors/BibliotheksFehler.ts
export class BibliotheksFehler extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'BibliotheksFehler';
  }
}

export class MediumNichtGefundenFehler extends BibliotheksFehler {
  constructor(public readonly isbn: string) {
    super(`Medium mit ISBN ${isbn} wurde nicht gefunden.`);
    this.name = 'MediumNichtGefundenFehler';
  }
}

export class MediumNichtVerfuegbarFehler extends BibliotheksFehler {
  constructor(public readonly isbn: string, public readonly aktuellerStatus: string) {
    super(`Medium ${isbn} ist nicht verfügbar (Status: ${aktuellerStatus}).`);
    this.name = 'MediumNichtVerfuegbarFehler';
  }
}

GENAU Vererbung aus Kapitel 13, angewendet auf die eingebaute Error-Klasse – MediumNichtGefundenFehler und MediumNichtVerfuegbarFehler tragen ZUSÄTZLICHE, typisierte Informationen (isbn, aktuellerStatus) über den reinen message-String hinaus.

// In Bibliothek.ts:
leiheAus(isbn: string): void {
  const medium = this.bestand.find((m) => m.isbn === isbn);
  if (!medium) {
    throw new MediumNichtGefundenFehler(isbn);
  }
  if (medium.status !== 'verfuegbar') {
    throw new MediumNichtVerfuegbarFehler(isbn, medium.status);
  }
  medium.status = 'ausgeliehen';
}
try {
  bibliothek.leiheAus('999');
} catch (error) {
  if (error instanceof MediumNichtGefundenFehler) {
    console.log(`Bitte ISBN prüfen: ${error.isbn}`); // typisierter Zugriff auf isbn!
  } else if (error instanceof MediumNichtVerfuegbarFehler) {
    console.log(`Status war: ${error.aktuellerStatus}`);
  }
}

Alternative: das Result-Type-Pattern

throw/catch hat einen Nachteil: der Funktions-TYP selbst zeigt NICHT, dass ein Fehler möglich ist – Aufrufer müssen die Dokumentation lesen oder es "einfach wissen". Das Result-Type-Pattern macht Fehler EXPLIZIT Teil der Signatur:

src/types/Result.ts
export type Result<T, E = Error> =
  | { erfolg: true; wert: T }
  | { erfolg: false; fehler: E };

export function erfolg<T>(wert: T): Result<T, never> {
  return { erfolg: true, wert };
}

export function fehlgeschlagen<E>(fehler: E): Result<never, E> {
  return { erfolg: false, fehler };
}
leiheAus(isbn: string): Result<void, BibliotheksFehler> {
  const medium = this.bestand.find((m) => m.isbn === isbn);
  if (!medium) {
    return fehlgeschlagen(new MediumNichtGefundenFehler(isbn));
  }
  if (medium.status !== 'verfuegbar') {
    return fehlgeschlagen(new MediumNichtVerfuegbarFehler(isbn, medium.status));
  }
  medium.status = 'ausgeliehen';
  return erfolg(undefined);
}

const ergebnis = bibliothek.leiheAus('123');
if (ergebnis.erfolg) {
  console.log('Ausleihe erfolgreich!'); // TypeScript weiß: ergebnis.wert existiert (Discriminated Union, Kapitel 9!)
} else {
  console.log(`Fehler: ${ergebnis.fehler.message}`); // TypeScript weiß: ergebnis.fehler existiert
}

Result<T, E> ist eine Discriminated Union (Kapitel 9) MIT Generics (Kapitel 17) kombiniert – der erfolg-Boolean ist der Diskriminator. Der GROSSE Vorteil: der RÜCKGABETYP Result<void, BibliotheksFehler> zeigt SOFORT, ohne Dokumentation zu lesen, dass diese Methode fehlschlagen KANN – ein Aufrufer, der ergebnis.wert liest, OHNE vorher ergebnis.erfolg zu prüfen, bekommt einen KOMPILIERZEIT-Fehler, nicht erst einen Laufzeit-Crash.

MusterWann geeignet
throw/catchVertraut, JavaScript-Standard, funktioniert gut für UNERWARTETE, seltene Fehler (Programmierfehler, kaputte Daten).
Result-TypeFehler sind Teil der TYP-Signatur, ERZWUNGENE Behandlung durch den Compiler, ideal für ERWARTETE, häufige "Fehlerfälle" (Validierung, Geschäftslogik-Regeln wie "Buch nicht verfügbar").

Tipp: Faustregel: throw für WIRKLICH AUSSERGEWÖHNLICHE Situationen (ein Bug, korrupte Daten, ein Netzwerk, das komplett unerreichbar ist), Result-Type für ERWARTBARE "Fehlerpfade", die Teil des normalen Programmablaufs SIND ("Buch schon ausgeliehen" ist kein BUG, sondern ein normaler Geschäftsfall). Beide Muster können im selben Projekt nebeneinander existieren.