Interfaces und Types in TypeScript

Interfaces und Type-Aliase beschreiben die Form deiner Daten. Du lernst, wann du was einsetzt und wie du eigene Strukturen sauber typisierst.

Teilen
Interfaces und Types in TypeScript

Sobald deine TypeScript-Projekte über einfache Variablen hinauswachsen, brauchst du Möglichkeiten, die Form komplexer Objekte zu beschreiben. Dafür gibt es zwei zentrale Werkzeuge: Interfaces und Type-Aliase. Beide legen fest, welche Eigenschaften ein Objekt haben muss und welchen Typ diese haben. In diesem Beitrag schauen wir uns beide an, vergleichen sie und du erfährst, wann sich welches eignet.

Was ist ein Interface?

Ein interface beschreibt die Struktur eines Objekts. Du gibst an, welche Eigenschaften vorhanden sein müssen und welchen Typ sie haben. Anschließend kannst du das Interface wie einen Typ verwenden:

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

const anna: Benutzer = {
  id: 1,
  name: "Anna",
  email: "anna@example.com"
};

// Fehlt eine Eigenschaft, meldet der Compiler einen Fehler:
// const fehlerhaft: Benutzer = { id: 2, name: "Tom" };

Das Interface dient als Vertrag. Jedes Objekt vom Typ Benutzer muss exakt diese Felder bereitstellen.

Optionale und schreibgeschützte Eigenschaften

Nicht jede Eigenschaft ist immer vorhanden. Mit einem Fragezeichen markierst du sie als optional. Mit readonly verhinderst du, dass ein Wert nachträglich geändert wird:

interface Produkt {
  readonly id: number;
  name: string;
  beschreibung?: string; // optional
}

const buch: Produkt = { id: 10, name: "TypeScript Buch" };
buch.name = "Neues Buch"; // erlaubt
// buch.id = 99; // Fehler: id ist readonly

// beschreibung darf fehlen, kann aber gesetzt werden:
const stift: Produkt = { id: 11, name: "Stift", beschreibung: "Blau" };

Type-Aliase als Alternative

Ein Type-Alias mit dem Schlüsselwort type kann ebenfalls Objektstrukturen beschreiben, ist aber flexibler. Du kannst damit auch Vereinigungen, primitive Typen oder Funktionssignaturen benennen:

type Punkt = {
  x: number;
  y: number;
};

// Union-Typ: nur diese Werte sind erlaubt
type Status = "offen" | "geschlossen" | "wartend";

// Ein benannter Funktionstyp
type Rechenoperation = (a: number, b: number) => number;

const ursprung: Punkt = { x: 0, y: 0 };
let zustand: Status = "offen";
const multipliziere: Rechenoperation = (a, b) => a * b;

Besonders die Union-Typen sind mit type sehr elegant. Mit einem Interface ließe sich der Status aus dem Beispiel nicht so kompakt ausdrücken.

Vererbung und Kombination

Interfaces lassen sich erweitern, sodass du auf bestehenden Strukturen aufbauen kannst. Bei Type-Aliasen erreichst du Ähnliches mit dem Schnittmengen-Operator &:

interface Lebewesen {
  name: string;
}

interface Tier extends Lebewesen {
  art: string;
}

const katze: Tier = { name: "Minka", art: "Katze" };

// Dasselbe mit Type-Aliasen:
type Basis = { name: string };
type Erweitert = Basis & { art: string };

const hund: Erweitert = { name: "Rex", art: "Hund" };

Wann nimmst du was?

Die Faustregel ist einfach: Für die Beschreibung von Objekten und Klassen sind Interfaces oft die erste Wahl, weil sie sich erweitern lassen und in Fehlermeldungen gut lesbar sind. Für alles andere, also Union-Typen, Tupel oder benannte Funktionstypen, greifst du zu type. In der Praxis funktionieren beide in vielen Fällen austauschbar:

// Interface für ein Objekt
interface Konto {
  inhaber: string;
  saldo: number;
}

// Type-Alias mit Union für einen begrenzten Wertebereich
type Waehrung = "EUR" | "USD" | "GBP";

interface KontoMitWaehrung extends Konto {
  waehrung: Waehrung;
}

const meinKonto: KontoMitWaehrung = {
  inhaber: "Anna",
  saldo: 1000,
  waehrung: "EUR"
};

Fazit

Interfaces und Type-Aliase sind das Rückgrat sauberer TypeScript-Projekte. Mit ihnen beschreibst du die Form deiner Daten klar und nachvollziehbar. Interfaces glänzen bei objektorientierten Strukturen und Vererbung, während Type-Aliase mit Union-Typen und flexiblen Kombinationen punkten. Beginne damit, deine wichtigsten Datenstrukturen zu typisieren. Du wirst feststellen, dass dein Code dadurch nicht nur sicherer, sondern auch deutlich selbsterklärender wird.