Zum Inhalt springen
aviral gupta

// B2.4 · ca. 28 Min. · Einstieg

Typaliase und Interfaces im Vergleich

Nach dieser Lektion benennen Sie einen Typ einmal mit type oder interface, bauen einen Typ auf einem anderen auf und wählen begründet zwischen beiden.

Lektion 4 von 5 in B2 Alltägliche Typen

Danach können Sie

  • Einen Objekttyp mit einem Typalias oder einem Interface benennen und den Namen in Annotationen verwenden
  • Einen Typ auf einem anderen aufbauen: ein Interface mit extends, einen Typalias mit &
  • Den wichtigsten Unterschied, Declaration Merging, erklären und zwischen type und interface wählen
  1. Aufwärmen · Aufgabe 1 von 7

    Aus der letzten Lektion: Was trifft auf Objekttypen wie { name: string; email?: string } zu? Wählen Sie alle zutreffenden.

    Wählen Sie alle zutreffenden aus.

  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es vorher, bevor Sie weiterlesen: Eine Produkt-Id landet in einer Variablen für eine Nutzer-Id. Was meldet tsc?

    type UserId = string;
    type ProductId = string;
    
    let current: UserId = "u-17";
    const product: ProductId = "p-9";
    current = product;
    console.log(current);
  3. Üben · Aufgabe 3 von 7

    Setzen Sie das Schlüsselwort ein, mit dem Dog jede Eigenschaft von Animal bekommt, damit tsc rex akzeptiert und das Programm Rex the Collie ausgibt.

    interface Animal {
      name: string;
    }
    
    interface Dog ____ Animal {
      breed: string;
    }
    
    const rex: Dog = { name: "Rex", breed: "Collie" };
    console.log(rex.name + " the " + rex.breed);
    interface Dog Animal {
  4. Üben · Aufgabe 4 von 7

    Person ist eine Intersection zweier Aliase. Was meldet tsc zuerst?

    type Named = { name: string };
    type Aged = { age: number };
    type Person = Named & Aged;
    
    const ada: Person = { name: "Ada" };
  5. Üben · Aufgabe 5 von 7

    Ordnen Sie jeder Deklaration zu, was sie tut.

  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Box ist zweimal deklariert, und box hat nur eine width. Was meldet tsc?

    interface Box {
      width: number;
    }
    
    interface Box {
      height: number;
    }
    
    const box: Box = { width: 2 };
  7. Anwenden · Aufgabe 7 von 7

    Kleine Aufgabe. Deklarieren Sie ein Interface Person mit name und optionaler email und ein Interface Employee, das Person um team erweitert. Schreiben Sie badge(employee: Employee), das Text wie Ada (Compilers) liefert, und rufen Sie es einmal auf. Schreiben Sie Employee danach als Typalias mit &, und prüfen Sie, dass tsc denselben Code weiterhin akzeptiert.

    Prüfen Sie Ihr Ergebnis anhand dieser Liste

Selbst programmieren

Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.

Ausgearbeitetes Beispiel

Benannte Typen für einen kleinen Katalog

Der Katalog enthält Bücher und Filme. ID ist ein Typalias, der eine Zahl oder einen String annimmt. Item ist ein Interface mit den Eigenschaften, die beide Arten teilen. Book erweitert Item mit extends; Film ist ein Typalias, der Item stattdessen mit & kombiniert. Jede Funktion nennt den Typ einmal in ihrer Signatur. Führen Sie npx tsc aus, dann node main.ts. Lassen Sie danach im letzten Aufruf pages weg, oder deklarieren Sie interface Item ein zweites Mal mit einer weiteren Eigenschaft, und lesen Sie, was tsc sagt.

main.ts

// Named types for a small library catalogue.
type ID = number | string;

interface Item {
  id: ID;
  title: string;
}

interface Book extends Item {
  author: string;
  pages: number;
}

type Film = Item & {
  minutes: number;
};

function describeBook(book: Book): string {
  return book.id + ": " + book.title + " by " + book.author + ", " + book.pages + " pages";
}

function describeFilm(film: Film): string {
  return film.id + ": " + film.title + ", " + film.minutes + " min";
}

const dune: Book = { id: 1, title: "Dune", author: "Frank Herbert", pages: 412 };
const metropolis: Film = { id: "F-7", title: "Metropolis", minutes: 153 };
console.log(describeBook(dune));
console.log(describeFilm(metropolis));
console.log(describeBook({ id: 2, title: "Emma", author: "Jane Austen", pages: 474 }));

Ausführen mit

npx tsc
node main.ts

Ausgabe

1: Dune by Frank Herbert, 412 pages
F-7: Metropolis, 153 min
2: Emma by Jane Austen, 474 pages
  • dune hat eine Zahl als id, metropolis einen String: ID nimmt beides an.
  • Book und Film bekommen id und title von Item, einmal über extends, einmal über &.
  • Der letzte Aufruf übergibt ein Objektliteral direkt an describeBook; es wird wie jedes andere gegen Book geprüft.
  • Die Namen gibt es nur für tsc: Node.js entfernt sie, und die Ausgabe ist die von einfachem JavaScript.
Ändern und ausführen

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.

Übungen

Übung 1 von 2

Den Typ benennen, den beide Funktionen verwenden

Beide Funktionen nehmen ein Product, aber tsc meldet Cannot find name 'Product'. Deklarieren Sie Product darüber, als Interface oder Typalias, mit name (string) und price (number). Ändern Sie nichts an den Funktionen. Starten Sie die Tests: Der erste ist die Typprüfung.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Beide Meldungen sind gleich: Der Name Product wird verwendet, aber nie deklariert.

  2. Hinweis 2

    Ein Interface hat kein =: interface Product { … }. Ein Typalias hat eins: type Product = { … };

  3. Hinweis 3

    interface Product { name: string; price: number; } über der ersten Funktion genügt.

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

interface Product {
  name: string;
  price: number;
}

export function label(product: Product): string {
  return product.name + ": " + product.price.toFixed(2) + " EUR";
}

export function isCheap(product: Product): boolean {
  return product.price < 5;
}
Auf dem eigenen Computer ausführen

Installieren Sie TypeScript 7.0 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.ts

export function label(product: Product): string {
  return product.name + ": " + product.price.toFixed(2) + " EUR";
}

export function isCheap(product: Product): boolean {
  return product.price < 5;
}

main.test.ts

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {label, isCheap} from './main.ts';

test('label zeigt Name und Preis', () => {
  assert.equal(label({name: 'Pen', price: 1.5}), 'Pen: 1.50 EUR', 'label sollte Pen: 1.50 EUR liefern');
});

test('isCheap ist unter 5 true', () => {
  assert.equal(isCheap({name: 'Pen', price: 1.5}), true, 'ein Preis von 1.5 sollte günstig sein');
});

test('isCheap ist ab 5 false', () => {
  assert.equal(isCheap({name: 'Mug', price: 8}), false, 'ein Preis von 8 sollte nicht günstig sein');
});

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [],
    "strict": true,
    "noEmit": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "**/*.test.ts"
  ]
}

npx tsc braucht TypeScript im Ordner: Führen Sie dort einmal npm install --save-dev typescript aus. tsc prüft die Typen; Node.js führt main.ts aus, indem es sie entfernt.

Programm ausführen:

npx tsc
node main.ts

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

npx tsc
node --test
learnrun.js herunterladen

Übung 2 von 2

Dog auf Animal aufbauen

describe liest name und legs aus einem Dog, aber Dog deklariert nur breed: tsc meldet Property 'name' does not exist on type 'Dog', und dasselbe für legs. Kopieren Sie die Eigenschaften nicht nach Dog. Lassen Sie Dog stattdessen auf Animal aufbauen, damit es jede Eigenschaft von Animal plus breed hat.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Das JavaScript läuft: Nur die Typprüfung scheitert, weil Dog name und legs nicht kennt.

  2. Hinweis 2

    Ein Schlüsselwort nach interface Dog lässt es alle Member eines anderen Interfaces übernehmen.

  3. Hinweis 3

    Schreiben Sie interface Dog extends Animal {

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

interface Animal {
  name: string;
  legs: number;
}

interface Dog extends Animal {
  breed: string;
}

export function describe(dog: Dog): string {
  return dog.name + " the " + dog.breed + " has " + dog.legs + " legs";
}
Auf dem eigenen Computer ausführen

Installieren Sie TypeScript 7.0 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.ts

interface Animal {
  name: string;
  legs: number;
}

interface Dog {
  breed: string;
}

export function describe(dog: Dog): string {
  return dog.name + " the " + dog.breed + " has " + dog.legs + " legs";
}

main.test.ts

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {describe} from './main.ts';

test('describe nennt den Hund, seine Rasse und seine Beine', () => {
  assert.equal(describe({name: 'Rex', breed: 'Collie', legs: 4}), 'Rex the Collie has 4 legs', 'describe sollte Rex the Collie has 4 legs liefern');
});

test('describe funktioniert auch für einen anderen Hund', () => {
  assert.equal(describe({name: 'Tripod', breed: 'Beagle', legs: 3}), 'Tripod the Beagle has 3 legs', 'describe sollte Tripod the Beagle has 3 legs liefern');
});

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [],
    "strict": true,
    "noEmit": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "**/*.test.ts"
  ]
}

npx tsc braucht TypeScript im Ordner: Führen Sie dort einmal npm install --save-dev typescript aus. tsc prüft die Typen; Node.js führt main.ts aus, indem es sie entfernt.

Programm ausführen:

npx tsc
node main.ts

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

npx tsc
node --test
learnrun.js herunterladen

Häufige Fehler

Ein = nach interface

interface Point = {
  x: number;
  y: number;
};

Was tsc oder Node.js ausgibt

main.ts(1,17): error TS1005: '{' expected.

Warum, und die Lösung

type und interface werden unterschiedlich geschrieben. Ein Typalias braucht =: type Point = { x: number; y: number };. Ein Interface hat kein =, die geschweiften Klammern folgen dem Namen: interface Point { x: number; y: number }. Die Meldung '{' expected zeigt auf das =, Spalte 17, wo tsc die Klammer erwartet hat.

Derselbe Typalias zweimal deklariert

type Settings = { theme: string };
type Settings = { fontSize: number };

Was tsc oder Node.js ausgibt

main.ts(1,6): error TS2300: Duplicate identifier 'Settings'.

Warum, und die Lösung

Ein Typalias lässt sich nicht wieder öffnen, also meldet tsc beide Deklarationen (Zeile 1 und 2). Fassen Sie alle Eigenschaften in einer zusammen: type Settings = { theme: string; fontSize: number };. Zwei Deklarationen interface Settings würden stattdessen verschmelzen, was erlaubt ist, aber eine zweite Deklaration weit weg in der Datei übersieht man leicht; behalten Sie eine.

Eine Eigenschaft des Basis-Interfaces vergessen

interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}

const rex: Dog = { breed: "Collie" };

Was tsc oder Node.js ausgibt

main.ts(9,7): error TS2741: Property 'name' is missing in type '{ breed: string; }' but required in type 'Dog'.

Warum, und die Lösung

Dog erweitert Animal, also braucht ein Dog jede Eigenschaft von Animal und dazu seine eigenen. Die Meldung nennt die fehlende, name, und den Typ, der sie verlangt, Dog. Ergänzen Sie sie: { name: "Rex", breed: "Collie" }.

TypeScript im Browser: der Compiler von TypeScript 6.0.3, Apache-2.0, danach die eigene Engine Ihres Browsers. Lizenz und Quellcode

Abschlussquiz

5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.

Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.

Problem melden

Etwas ist falsch oder unklar? Beschreiben Sie es kurz, dann wird es geprüft und korrigiert.

#

Mindestens 20 Zeichen.

Nur, wenn Sie eine Antwort wünschen.

Kernideen

Ein Typalias gibt einem Typ einen Namen

type Point = { x: number; y: number }; benennt einen Objekttyp: Sie schreiben ihn einmal und annotieren überall sonst mit Point. Ein Alias kann jeden Typ benennen, nicht nur Objekte: type ID = number | string benennt einen Typ, der eine Zahl oder einen String annimmt (Union-Typen kommen in Modul B3). Ein Alias ist nur ein Name: Ihn zu verwenden, ist genau so, als hätten Sie den Typ ausgeschrieben. Nach type UserId = string und type ProductId = string sind also beide einfach string, und tsc lässt Sie sie verwechseln. Typnamen schreibt man üblicherweise in PascalCase, und tsc verwendet sie in seinen Meldungen: … but required in type 'Point'.

Ein Interface benennt einen Objekttyp, und extends baut auf einem auf

interface Point { x: number; y: number } ist der andere Weg, einen Objekttyp zu benennen: ohne =, die Eigenschaften stehen direkt in den geschweiften Klammern. Ein Interface kann mit extends auf einem anderen aufbauen: interface Book extends Item { author: string } übernimmt die Member von Item in Book und ergänzt author, und interface C extends A, B {} kombiniert zwei. Ein Typalias kombiniert Typen stattdessen mit &, einer Intersection: type Film = Item & { minutes: number } hat jede Eigenschaft beider Seiten. In beiden Fällen braucht ein Wert des neuen Typs alle davon, und tsc nennt die fehlende. Intersections im Detail und was bei widersprüchlichen Eigenschaften passiert, kommen in Modul B5.

Der wichtigste Unterschied und welche Form Sie wählen

Die beiden sind fast austauschbar. Das Handbuch nennt den wichtigsten Unterschied: Ein Interface lässt sich wieder öffnen, ein Typalias nicht. Zwei Deklarationen interface Box verschmelzen zu einem Box mit den Eigenschaften beider, das heißt Declaration Merging; zwei Deklarationen type Box sind error TS2300: Duplicate identifier 'Box'. Bibliotheken nutzen das Verschmelzen, damit Sie Typen wie Window ergänzen können; in Ihrem eigenen Code ist es öfter eine Überraschung. Nur ein Typalias kann einen primitiven Typ oder eine Union benennen, etwa type ID = number | string; interface ID = string ist ein Syntaxfehler. Die Faustregel des Handbuchs: Nehmen Sie interface, bis Sie eine Fähigkeit von type brauchen.

Quellen

Zuletzt geprüft am 30. September 2026