Praxis

Async/Await in TypeScript: Promises richtig typisieren

Lerne, wie du asynchronen Code in TypeScript mit async/await und korrekten Promise-Typen schreibst. Mit praktischen Beispielen und häufigen Fallstricken.

Lesezeit 7 Min. Aktualisiert 22.05.2026 2 Quellen Mateusz Viola Mateusz Viola
Inhalt

Asynchroner Code ist in modernen Webanwendungen unvermeidlich. Netzwerkanfragen, Datenbankzugriffe und Dateioperationen laufen alle asynchron ab. TypeScript erweitert das aus JavaScript bekannte async/await-Muster um ein starkes Typsystem, das dir hilft, Fehler bereits beim Kompilieren zu erkennen.

Grundlagen: Promise-Typen in TypeScript

Eine async-Funktion gibt immer ein Promise zurück. TypeScript leitet den Typ automatisch ab, aber es ist gute Praxis, ihn explizit anzugeben:

async function ladeDaten(): Promise<string> {
  return "Hallo TypeScript";
}

async function speichereDaten(wert: string): Promise<void> {
  console.log(`Gespeichert: ${wert}`);
}

Der generische Parameter von Promise<T> beschreibt den Typ des aufgelösten Werts. Wenn die Funktion nichts zurückgibt, verwendest du Promise<void>.

Typisierte API-Aufrufe mit fetch

Ein häufiger Anwendungsfall ist das Abrufen von Daten über eine API. Ohne TypeScript weißt du nicht, welche Struktur die Antwort hat. Mit Interfaces kannst du das präzise festlegen:

interface Benutzer {
  id: number;
  name: string;
  email: string;
}

async function ladeBenutzer(id: number): Promise<Benutzer> {
  const antwort = await fetch(`https://api.beispiel.de/benutzer/${id}`);

  if (!antwort.ok) {
    throw new Error(`HTTP-Fehler: ${antwort.status}`);
  }

  const daten: Benutzer = await antwort.json();
  return daten;
}

Beachte, dass fetch selbst Promise<Response> zurückgibt und response.json() den Typ Promise<unknown> hat. Die explizite Typzuweisung schützt dich vor falschen Annahmen.

Fehlerbehandlung mit try/catch

Fehlerbehandlung ist bei asynchronem Code besonders wichtig. TypeScript kann dir dabei helfen, Fehlertypen korrekt zu behandeln:

interface ApiError {
  message: string;
  statusCode: number;
}

async function sichereLadeOperation(): Promise<Benutzer | null> {
  try {
    const benutzer = await ladeBenutzer(1);
    return benutzer;
  } catch (fehler: unknown) {
    if (fehler instanceof Error) {
      console.error(`Fehler aufgetreten: ${fehler.message}`);
    }
    return null;
  }
}

Seit TypeScript 4.0 ist der Typ von catch-Variablen standardmäßig unknown. Das zwingt dich, den Typ zu prüfen, bevor du darauf zugreifst.

Parallele Ausführung mit Promise.all

Wenn mehrere unabhängige Operationen gleichzeitig ausgeführt werden können, solltest du sie parallelisieren. TypeScript leitet dabei die Typen korrekt ab:

async function ladeAllesDaten(): Promise<[Benutzer, string[]]> {
  const [benutzer, beitraege] = await Promise.all([
    ladeBenutzer(1),
    ladeBeitraege(1),
  ]);

  return [benutzer, beitraege];
}

async function ladeBeitraege(benutzerId: number): Promise<string[]> {
  return ["Beitrag 1", "Beitrag 2"];
}

Promise.all gibt ein Tuple zurück, dessen Typen TypeScript automatisch ableitet. Das Ergebnis ist vollständig typisiert.

Utility-Typen für Promises

TypeScript bietet hilfreiche eingebaute Typen für die Arbeit mit Promises:

// Awaited<T> extrahiert den aufgelösten Typ eines Promise
type BenutzerTyp = Awaited<Promise<Benutzer>>;
// entspricht: Benutzer

// Nützlich bei verschachtelten Promises
type TiefesPromise = Awaited<Promise<Promise<string>>>;
// entspricht: string

Awaited<T> ist besonders nützlich, wenn du den Rückgabetyp einer async-Funktion in einem anderen Kontext benötigst.

Generische async-Funktionen

Du kannst generische async-Funktionen schreiben, die für verschiedene Datentypen funktionieren:

async function ladeUndVerarbeite<T>(
  url: string,
  verarbeitung: (daten: T) => T
): Promise<T> {
  const antwort = await fetch(url);
  const daten: T = await antwort.json();
  return verarbeitung(daten);
}

// Verwendung
const ergebnis = await ladeUndVerarbeite<Benutzer>(
  "https://api.beispiel.de/benutzer/1",
  (b) => ({ ...b, name: b.name.toUpperCase() })
);

Generics machen deine asynchronen Funktionen wiederverwendbar, ohne auf die Typsicherheit zu verzichten.

Häufige Fallstricke

Ein verbreiteter Fehler ist das Vergessen von await beim Aufruf einer async-Funktion. TypeScript warnt dich in diesem Fall, wenn du noImplicitReturns aktiviert hast:

// Falsch: benutzer ist Promise<Benutzer>, nicht Benutzer
const benutzer = ladeBenutzer(1);
console.log(benutzer.name); // TypeScript-Fehler!

// Richtig
const benutzer = await ladeBenutzer(1);
console.log(benutzer.name); // string

Ein weiterer Fallstrick ist das Verwechseln von Promise.all und Promise.allSettled. Mit Promise.all wird das gesamte Promise abgebrochen, sobald ein einzelnes Promise fehlschlägt.

Im Playground ausprobieren

Das Playground auf dieser Seite eignet sich hervorragend, um async/await-Code direkt im Browser zu testen. Du kannst dort die Typen überprüfen und Fehler sofort sehen, ohne ein lokales Projekt einrichten zu müssen.

Fazit

TypeScript macht asynchronen Code deutlich sicherer und besser wartbar. Durch explizite Promise-Typen, typisierte Fehlerbehandlung und den Awaited<T>-Utility-Typ hast du jederzeit die Kontrolle über den Datenfluss in deiner Anwendung. Starte mit einfachen async-Funktionen und erweitere dein Wissen schrittweise um generische Patterns und parallele Ausführung.

Häufige Fragen

Was ist der Unterschied zwischen Promise<void> und Promise<undefined>?

Promise<void> signalisiert, dass der Rückgabewert nicht verwendet werden soll. Promise<undefined> gibt explizit undefined zurück. Für Funktionen ohne sinnvollen Rückgabewert sollte man Promise<void> verwenden.

Kann ich await außerhalb einer async-Funktion verwenden?

In modernen ES-Modulen ist Top-Level-Await möglich. In TypeScript funktioniert das ab Version 3.8 mit dem Compiler-Flag module: 'esnext' oder 'node16'.

Wie behandle ich Fehler bei mehreren parallelen Promises?

Mit Promise.allSettled erhältst du alle Ergebnisse, auch wenn einzelne Promises fehlschlagen. Promise.all hingegen bricht bei dem ersten Fehler ab.

Quellen

  • TypeScript Handbook: Async Functions (typescriptlang.org)
  • MDN Web Docs: async function
Mateusz Viola

Über die Autorenschaft

Mateusz Viola

Betreiber und redaktionelle Verantwortung typescript-playground.de

Themengebiet: Mathematik, Kalenderrechnung, Schaltjahre, Statistik und ISO 8601

Mehr über Mateusz Viola →

Verwandte Artikel

TypeScript Playground nutzen

Sofort im Browser, ohne Anmeldung.

Zum Playground