Fehlerbehandlung in TypeScript: try/catch, benutzerdefinierte Klassen und strenge Typisierung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Fehlerbehandlung in TypeScript mehr als nur try/catch ist

TypeScript fügt JavaScript statische Typisierung hinzu, aber Laufzeitfehler (runtime errors) bleiben Teil jeder Anwendung. Im Gegensatz zu reinem JS, wo catch(e) any zurückgibt, bietet TypeScript strengere Mechanismen. Richtige Fehlerbehandlung bedeutet nicht nur, Abstürze zu verhindern, sondern auch ein verständliches System zum Debuggen und zur Code-Wartung zu schaffen. In diesem Artikel behandeln wir alle Aspekte: vom grundlegenden try/catch bis zur Erstellung benutzerdefinierter Fehlerhierarchien mit vollständiger Typisierung.



1. Grundlegende Syntax von try/catch und das Problem des Typs unknown

Klassische Konstruktion

Die grundlegende Konstruktion in TypeScript sieht genauso aus wie in JavaScript:

try {    // Code, der eine Exception werfen kann    const data = JSON.parse('{"name": "TypeScript"}');    console.log(data.name);} catch (error) {    // Fehlerbehandlung    console.error('Ein Fehler ist aufgetreten:', error);}

Es gibt jedoch einen wichtigen Unterschied: In TypeScript hat die Variable error im catch-Block den Typ unknown (und nicht any wie in JavaScript, sofern nicht anders angegeben). Dies dient der Typsicherheit.



Das Problem mit unknown und wie man es löst

Der Typ unknown bedeutet, dass wir nicht einfach auf Eigenschaften des Fehlers zugreifen können, z.B. error.message. Der Compiler gibt einen Fehler aus:

catch (error) {    // Fehler TS2571: Object is of type 'unknown'.    console.log(error.message); // ❌ Wird nicht kompiliert}

Um auf die Eigenschaften zuzugreifen, muss der Typ eingeengt werden:

catch (error) {    if (error instanceof Error) {        console.log(error.message); // ✅ Funktioniert    } else {        console.log('Unbekannter Fehler:', error);    }}

Oder man verwendet eine Prüfung auf das Vorhandensein der Eigenschaft:

catch (error) {    if (error && typeof error === 'object' && 'message' in error) {        console.log((error as { message: string }).message);    }}


2. Erstellung benutzerdefinierter Fehlerklassen mit Typisierung

Warum ist das wichtig?

Der Standard-Error enthält nur name, message und stack. In realen Projekten werden oft zusätzliche Felder benötigt: Fehlercode, HTTP-Status, Daten für das Logging. TypeScript ermöglicht die Erstellung einer Fehlerklassenhierarchie mit vollständiger Typunterstützung.



Beispiel einer benutzerdefinierten Klasse

// Basisklasse für alle Anwendungsfehlerclass AppError extends Error {    public readonly statusCode: number;    public readonly isOperational: boolean;

constructor(message: string, statusCode: number = 500, isOperational: boolean = true) { super(message); this.name = 'AppError'; this.statusCode = statusCode; this.isOperational = isOperational; // Prototyp wiederherstellen (notwendig für TypeScript) Object.setPrototypeOf(this, new.target.prototype); }}

// Spezialisierte Fehlerclass NotFoundError extends AppError { constructor(resource: string) { super(`${resource} nicht gefunden`, 404); this.name = 'NotFoundError'; }}

class ValidationError extends AppError { public readonly errors: string[];

constructor(errors: string[]) { super('Validierungsfehler', 400); this.name = 'ValidationError'; this.errors = errors; }}


Verwendung mit try/catch

function getUser(id: number): User {    if (id <= 0) {        throw new ValidationError(['ID muss eine positive Zahl sein']);    }    // ... Logik zum Abrufen des Benutzers    if (!user) {        throw new NotFoundError('Benutzer');    }    return user;}

try { const user = getUser(-1);} catch (error) { if (err

Blogs

Buchempfehlungen