TypeScript-Typen aus JSON generieren — richtig gemacht
Typen aus einer Beispielantwort zu erzeugen dauert nur Sekunden. Typen, denen du vertrauen kannst, brauchen ein paar weitere Entscheidungen: Was ist optional, was nullable, wie benennst du Dinge und wie stellst du sicher, dass die API zur Laufzeit hält, was sie verspricht?
Mit echten Beispielen starten
Füge eine Antwort in den JSON-zu-TypeScript-Konverter ein, und du erhältst Interfaces für jedes verschachtelte Objekt. Ein Beispiel zeigt aber nur eine Form. Füge daher ein Array aus mehreren echten Objekten ein: Der Konverter führt sie zusammen und markiert Felder, die in manchen fehlen, als optional.
[
{ "id": 1, "name": "Ada", "email": "ada@example.com", "team": { "id": 7, "name": "Core" } },
{ "id": 2, "name": "Grace", "email": null }
]
interface User {
id: number;
name: string;
email: string | null;
team?: Team;
}
interface Team {
id: number;
name: string;
}
Optional ist nicht nullable
team?: Team bedeutet, dass der Schlüssel fehlen kann. email: string | null bedeutet, dass der Schlüssel immer vorhanden ist, aber null sein kann. APIs verwenden beides unterschiedlich, und dein Code prüft es ebenfalls unterschiedlich ('team' in user vs. user.email === null). Behalte die Unterscheidung bei, statt alles als ?: … | null zu schreiben.
Was das Beispiel nicht verrät, selbst festlegen
- Literal-Unions — ein Feld
status, das als"active"vorkommt, wird zustring; ersetze es durch'active' | 'paused' | 'deleted'aus der API-Dokumentation. - Datumswerte kommen als ISO-Strings an. Typisiere sie als
stringund parse sie am Rand deines Codes — tu nicht so, als wären esDate-Objekte. - IDs — große numerische IDs (über 253) verlieren in JavaScript an Genauigkeit; deshalb senden viele APIs sie als Strings.
- Leere Arrays werden zu
unknown[]oderany[]; trage den Elementtyp selbst ein.
Typen verschwinden zur Laufzeit
TypeScript prüft deinen Code, nicht die Daten. Ändert sich die API, bemerkt der Compiler das nicht. Validiere Antworten deshalb an der Schnittstelle:
- Erzeuge ein Schema aus denselben Beispielen mit JSON zu JSON Schema.
- Bearbeite es — Pflichtfelder, Enums, Formate wie
date-time— und teste echte Payloads im JSON Schema Validator. - Validiere in deiner App mit einer Bibliothek wie Ajv und generiere die Typen aus dem Schema (JSON Schema zu TypeScript), damit es nur eine Quelle der Wahrheit gibt.
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(userSchema);
const data = await res.json();
if (!validate(data)) throw new Error('Unexpected API response: ' + ajv.errorsText(validate.errors));
Bibliotheken wie Zod oder Valibot machen dasselbe, nur wird das Schema direkt in TypeScript geschrieben und der Typ daraus abgeleitet.
Benennung und Struktur
Gib dem obersten Typ einen aussagekräftigen Namen (User, nicht Root), exportiere die Typen aus einem Modul und bevorzuge interface für Objektformen, die du erweitern möchtest. Formatiere und untersuche große Antworten zuerst mit dem JSON Formatter, damit du siehst, welche Zweige wichtig sind.