Woher kommen die Typen einer Bibliothek?
Wenn du ein JavaScript-Paket importierst, braucht TypeScript dessen Typen. Es gibt drei Fälle:
- Das Paket bringt Typen mit (Feld
typesin derpackage.json): nichts zu tun. Das gilt heute für die meisten modernen Pakete. - Typen kommen aus DefinitelyTyped: Installiere
npm install -D @types/<paket>, zum Beispiel@types/node,@types/express,@types/lodash. - 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 wirdany).
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üsselwort | Bedeutung |
|---|---|
declare const x: T | globale Variable |
declare function f(): T | globale 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
| Meldung | Bedeutung | Lösung |
|---|---|---|
TS2322: Type 'X' is not assignable to type 'Y' | falscher Typ zugewiesen | Typ anpassen oder Wert korrigieren |
TS2339: Property 'x' does not exist on type 'Y' | Eigenschaft gibt es nicht | Tippfehler? Typ erweitern? Narrowing? |
TS2531/TS18047: Object is possibly 'null' | Wert könnte null sein | prüfen (if, ?., ??) |
TS7006: Parameter 'x' implicitly has an 'any' type | Typ fehlt | Parameter beschriften |
TS2307: Cannot find module | Modul oder Typen fehlen | Pfad prüfen, @types/... installieren |
TS2345: Argument of type X is not assignable... | falsches Argument | Aufruf oder Funktionssignatur anpassen |
TS2554: Expected N arguments, but got M | falsche Argumentzahl | Aufruf 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
| Werkzeug | Wirkung | Risiko |
|---|---|---|
as Typ | Typ behaupten | falsche Behauptung bleibt unentdeckt |
x! (Non-null-Assertion) | "ist nicht null" | Absturz bei Irrtum |
// @ts-ignore | unterdrückt Fehler in der nächsten Zeile | versteckt echte Fehler |
// @ts-expect-error | wie ignore, aber meldet, wenn kein Fehler mehr da ist | besser als ignore |
any | keine Prüfung | steckt 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 typefür reine Typ-Importe; Module lassen sich erweitern- Fehlermeldungen von unten nach oben lesen
as,!,@ts-ignoreundanysind Notausgänge,@ts-expect-errorist besser alsignore
Aufgabe
Installiere ein Paket ohne eigene Typen (oder erfinde eins) und schreibe eine kleine .d.ts-Datei dafür mit zwei Funktionen und einem Interface.