EMZETT.
Login

Kurz: Wenn du ein JavaScript-Paket importierst, braucht TypeScript dessen Typen. Es gibt drei Fälle:

Teil des Kurses TypeScript

Kapitel 13 von 15 im Kurs TypeScript. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Woher kommen die Typen einer Bibliothek?

Wenn du ein JavaScript-Paket importierst, braucht TypeScript dessen Typen. Es gibt drei Fälle:

  1. Das Paket bringt Typen mit (Feld types in der package.json): nichts zu tun. Das gilt heute für die meisten modernen Pakete.
  2. Typen kommen aus DefinitelyTyped: Installiere npm install -D @types/<paket>, zum Beispiel @types/node, @types/express, @types/lodash.
  3. Es gibt keine Typen: Dann meldet TypeScript “Could not find a declaration file”. Du schreibst selbst eine Deklaration oder behilfst dich mit declare module "paket"; (alles wird any).

Deklarationsdateien (.d.ts)

Eine .d.ts-Datei enthält nur Typen, keinen Code. Sie beschreibt, was in einer JavaScript-Datei oder Bibliothek steckt:

// mathe-lib.d.ts
declare module "mathe-lib" {
  export function addiere(a: number, b: number): number;
  export const PI: number;
  export interface Optionen { runden?: boolean }
  export default function rechne(ausdruck: string, optionen?: Optionen): number;
}

Mit declare sagst du: “Das gibt es, ich beschreibe nur seine Form.”

SchlüsselwortBedeutung
declare const x: Tglobale Variable
declare function f(): Tglobale Funktion
declare module "name" { ... }Typen für ein Modul
declare global { ... }globale Typen aus einem Modul heraus ergänzen
interface Window { ... }vorhandenes Interface erweitern

Eigene Bibliothek mit Typen veröffentlichen

Wenn du in TypeScript schreibst, erzeugt der Compiler die Typen automatisch:

{
  "compilerOptions": { "declaration": true, "outDir": "dist" }
}

In der package.json verweist "types": "dist/index.d.ts" darauf. Neuere Projekte beschreiben das über das Feld exports.

Typ-Importe von Werten trennen

import type { IncomingMessage } from "node:http";      // nur Typ
 
function methode(a: IncomingMessage): string | undefined {
  return a.method;
}
console.log(typeof methode);

Ausgabe:

function

Module erweitern (Augmentation)

Manche Bibliotheken lassen sich um eigene Eigenschaften erweitern, etwa Express um req.user:

// types/express.d.ts
import "express";
declare module "express-serve-static-core" {
  interface Request { user?: { id: number; rolle: string } }
}

Typen testen

Auch Typen kann man testen: Prüfe, dass ein Typ das ist, was du erwartest. Mit einem Hilfstyp schlägt der Compiler Alarm, wenn sich ein Typ ändert:

type Gleich<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
type Erwartet<T extends true> = T;
 
type Test1 = Erwartet<Gleich<Awaited<Promise<number>>, number>>;      // kompiliert
// type Test2 = Erwartet<Gleich<string, number>>;                      // Fehler: false erfüllt true nicht
const ok: Test1 = true;
console.log(ok);

Ausgabe:

true

Fertige Hilfen bieten Werkzeuge wie tsd, expect-type oder vitest --typecheck.

Häufige Fehlermeldungen verstehen

MeldungBedeutungLösung
TS2322: Type 'X' is not assignable to type 'Y'falscher Typ zugewiesenTyp anpassen oder Wert korrigieren
TS2339: Property 'x' does not exist on type 'Y'Eigenschaft gibt es nichtTippfehler? Typ erweitern? Narrowing?
TS2531/TS18047: Object is possibly 'null'Wert könnte null seinprüfen (if, ?., ??)
TS7006: Parameter 'x' implicitly has an 'any' typeTyp fehltParameter beschriften
TS2307: Cannot find moduleModul oder Typen fehlenPfad prüfen, @types/... installieren
TS2345: Argument of type X is not assignable...falsches ArgumentAufruf oder Funktionssignatur anpassen
TS2554: Expected N arguments, but got Mfalsche ArgumentzahlAufruf korrigieren

Lies lange Fehlermeldungen von unten nach oben: Die letzte Zeile nennt meist die eigentliche Ursache.

interface Benutzer { name: string; adresse?: { stadt: string } }
const b: Benutzer = { name: "Mia" };
console.log(b.adresse.stadt);

Fehlermeldung:

error TS18048: 'b.adresse' is possibly 'undefined'.

Notausgänge, mit Verstand

WerkzeugWirkungRisiko
as TypTyp behauptenfalsche Behauptung bleibt unentdeckt
x! (Non-null-Assertion)“ist nicht null”Absturz bei Irrtum
// @ts-ignoreunterdrückt Fehler in der nächsten Zeileversteckt echte Fehler
// @ts-expect-errorwie ignore, aber meldet, wenn kein Fehler mehr da istbesser als ignore
anykeine Prüfungsteckt an

Sparsam einsetzen, immer mit Kommentar, warum.

Merke

  • Pakete bringen Typen mit oder haben @types/<paket>
  • .d.ts-Dateien beschreiben Typen ohne Code (declare)
  • import type für reine Typ-Importe; Module lassen sich erweitern
  • Fehlermeldungen von unten nach oben lesen
  • as, !, @ts-ignore und any sind Notausgänge, @ts-expect-error ist besser als ignore

Übungsaufgabe

Installiere ein Paket ohne eigene Typen (oder erfinde eins) und schreibe eine kleine .d.ts-Datei dafür mit zwei Funktionen und einem Interface.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: TypeScript im Browser und in Node.js

Weiter: Gute TypeScript-Praxis

Alle Kapitel: TypeScript im Überblick