Utilo

JSON zu TypeScript-Schnittstellen: Ein praktischer Leitfaden für die Eingabe von API-Antworten

Erfahren Sie, wie Sie JSON in genaue TypeScript-Schnittstellen umwandeln, optionale Felder, Nullen, Verbindungen und Arrays verarbeiten und Typen mit echten APIs synchronisieren.

· 5 Min. Lesezeit

Jedes TypeScript-Projekt, das mit einer API spricht, steht schließlich vor derselben Frage: Wie beschreibt man die Form von Daten, die als nicht getipptes JSON ankommen? Wenn man Antworten als any hinterlässt, wird der Hauptvorteil von TypeScript weggeworfen. Das Schreiben von Schnittstellen für eine 200-Zeilen-Nutzlast ist mühsam und fehleranfällig. Dieser Leitfaden führt Sie durch einen zuverlässigen Workflow für die Erstellung von Schnittstellen aus JSON, ihre Verfeinerung und ihre Ehrlichkeit im Laufe der Zeit.

Warum Typen für JSON wichtig sind

Wenn Sie await res.json() anrufen, gibt Ihnen TypeScript any. Von diesem Moment an werden Tippfehler wie user.adress.city ohne Beschwerde kompiliert und scheitern nur in der Laufzeit, oft in der Produktion und oft für eine Teilmenge von Benutzern, deren Daten zufällig abweichen. Eine eingegebene Antwort gibt Ihnen automatisches Ausfüllen, sicheres Refactoring und Kompilierungsfehler, wenn das Backend ein Feld umbenennt.

Typen dienen auch als Dokumentation. Ein neues Teammitglied, das interface Order { id: string; items: OrderItem[]; total: number; couponCode?: string } liest, lernt in fünf Sekunden mehr, als wenn es durch eine Probenantwort blättert.

Schritt 1: Beginnen Sie mit einer realen, repräsentativen Stichprobe

Die erzeugten Typen sind nur so gut wie die Probe, die man einträgt. Vor der Konvertierung eine Antwort sammeln, die so viele Felder wie möglich ausübt:

  • Wählen Sie einen Datensatz aus, in dem Optionsfelder ausgefüllt sind, z. B. eine Bestellung mit einem Gutschein, einer Lieferadresse und einer Geschenknachricht.
  • Eingliedern von Arrays mit mindestens einem Element; ein leeres Array sagt einem Generator nichts über seinen Inhalt.
  • Wenn ein Feld null sein kann, versuchen Sie, ein Beispiel einzubeziehen, bei dem es null ist, und ein Beispiel, bei dem es nicht ist.

Kopieren Sie den Antwortkörper aus dem Netzwerk-Tab Ihres Browsers oder aus curl, fügen Sie ihn in einen [JSON-Formatter] ((/tools/json) ein und bestätigen Sie seine Gültigkeit. Dann wechseln Sie den Modus auf → TypeScript.

Schritt 2: Erstellen des ersten Entwurfs

Angesichts dieser Eingabe:

{
  "id": "ord_9f2",
  "createdAt": "2026-09-30T12:01:44Z",
  "customer": { "id": 42, "email": "ana@example.com" },
  "items": [
    { "sku": "TSHIRT-M", "qty": 2, "price": 19.5 },
    { "sku": "MUG", "qty": 1, "price": 12 }
  ],
  "coupon": null
}

Ein Generator erzeugt so etwas wie:

export interface Customer {
  id: number;
  email: string;
}

export interface Item {
  sku: string;
  qty: number;
  price: number;
}

export interface Root {
  id: string;
  createdAt: string;
  customer: Customer;
  items: Item[];
  coupon: null;
}

Dies ist ein solider Ausgangspunkt, aber er spiegelt nur wider, was eine Probe enthielt. Die nächsten Schritte machen es zu einem Typ, der dem API-Vertrag entspricht.

Schritt 3: Umbenennung und Verbesserung

Generatoren benennen verschachtelte Schnittstellen nach Schlüsseln. Sie umbenennen in Domänenbegriffe: Root wird Order, Item wird OrderItem. Überprüfen Sie dann jedes Feld mit diesen Fragen.

Kann es fehlen? Wenn die API in einigen Antworten einen Schlüssel weglässt, markieren Sie ihn als optional mit ?. Optional (coupon?: Coupon) und nullbar (coupon: Coupon | null) unterscheiden sich: Das erste bedeutet, dass der Schlüssel möglicherweise fehlt, das zweite bedeutet, dass er immer vorhanden ist, aber null halten kann. Viele APIs tun beides, was man als coupon?: Coupon | null ausdrückt.

** War null der einzige Wert?** Ein Feld, das buchstäblich als null eingegeben ist, bedeutet fast immer, dass die Stichprobe nicht repräsentativ war. Ersetzen Sie es durch den echten Typ plus | null.

Ist eine Zeichenfolge wirklich eine Zeichenfolge? Die Daten werden als ISO 8601 Zeichenfolgen angezeigt. Bewahren Sie sie als string im Transporttyp auf; die Umwandlung in Date gehört zu einer Kartierungsschicht. Sie können Absichten mit einem Typen-Alias dokumentieren: type ISODateString = string.

Ist eine Zahl eine Enum? Wenn status immer einer von wenigen Werten ist, verwenden Sie eine Vereinigung von Literalen: status: "pending" | "paid" | "shipped". Das ergibt eine vollständige switch-Prüfung.

** Sind IDs als Zahlen sicher?** Datenbank-IDs über 2^53 verlieren in JavaScript an Präzision. Wenn Ihr Backend 64-Bit-Vollzahlen verwendet, bitten Sie es, IDs als Zeichenketten zu senden und schreiben Sie sie als string.

Das verfeinerte Ergebnis:

export type ISODateString = string;

export interface Order {
  id: string;
  createdAt: ISODateString;
  status: "pending" | "paid" | "shipped" | "cancelled";
  customer: Customer;
  items: OrderItem[];
  coupon?: Coupon | null;
}

Schritt 4: Handhabung von Arrays mit gemischten Inhalten

Einige APIs geben heterogene Arrays zurück, z. B. einen Aktivitätsfeed mit verschiedenen Ereignisarten. Ein naiver Generator erzeugt eine einzige Schnittstelle mit jedem Feld optional, die Informationen verliert. Eine diskriminierte Gewerkschaft ist viel besser:

type FeedEvent =
  | { type: "comment"; id: string; text: string }
  | { type: "like"; id: string; userId: string }
  | { type: "follow"; id: string; followerId: string };

Jetzt verengt TypeScript den Typ automatisch innerhalb von if (event.type === "comment"). Beim Umwandeln eines gemischten Arrays verbindet das Tool die abgeleiteten Elementtypen; nutzt diese Ausgabe als Hinweis, um die diskriminierte Union von Hand zu entwerfen.

Schritt 5: Validieren in der Laufzeit

TypScript-Typen verschwinden bei der Kompilierung. Wenn sich das Backend ändert, erhält Ihr Code immer noch die neue Form und Ihre Typen liegen still. Für Daten, die eine Vertrauensgrenze überschreiten, fügen Sie die Laufzeitvalidierung mit einer Schemabibliothek wie Zod, Valibot oder ArkType hinzu und leiten Sie den statischen Typ aus dem Schema ab:

import { z } from "zod";

const OrderSchema = z.object({
  id: z.string(),
  createdAt: z.string().datetime(),
  items: z.array(z.object({ sku: z.string(), qty: z.number().int(), price: z.number() })),
  coupon: z.object({ code: z.string() }).nullable().optional(),
});

export type Order = z.infer<typeof OrderSchema>;
const order = OrderSchema.parse(await res.json());

Sie können den Generator immer noch zum Bootstrappen verwenden: die Schnittstelle generieren und dann Feld für Feld ins Schema übersetzen.

Schritt 6: Die Quelle der Wahrheit bevorzugen, wenn sie existiert

Wenn Ihre API ein OpenAPI (Swagger) oder GraphQL-Schema veröffentlicht, generieren Sie Typen daraus anstelle von Samples. Tools wie openapi-typescript und GraphQL Code Generator produzieren exakte Typen einschließlich Optionalität und Enums, und sie können in CI ausgeführt werden, so dass Typen aktualisiert werden, wenn sich das Schema ändert. Probe-basierte Generation glänzt für APIs von Drittanbietern ohne Schemas, schnelle Prototypen, Webhooks und alte Dienste.

Schnittstelle oder Typ?

Für Objektformen sind interface und type fast austauschbar. Schnittstellen können erweitert und zusammengeführt werden, und Fehlermeldungen beziehen sich auf sie nach Namen, was bei großen Objekten hilft. Typen-Aliase sind für Unions-, Tupel- und abgegrenzte Typen erforderlich. Eine gemeinsame Konvention sind Schnittstellen für Objektformen und Typen-Aliase für alles andere.

Häufige Fallen

  • Alles als optional eingeben. Es fühlt sich sicher an, zwingt aber Nullprüfungen überall hin und verbirgt echte Vertragsverletzungen. Felder nur dann optional machen, wenn die API sie tatsächlich weglässt.
  • Vertrauen auf eine einzige Stichprobe. Überprüfen Sie die Dokumentation oder mehrere Antworten, bevor Sie die Optionalität abschließen.
  • Mischung von Transport- und Domänentypen. Bewahren Sie eine rohe OrderDTO, die JSON spiegelt, auf und zeichnen Sie sie in eine Domäne Order mit realen Date-Objekten und berechneten Feldern ab.
  • Vergessen von Pagination Wrappers. Viele APIs wickeln Listen in { data: [...], nextCursor: "..." }. Modellieren Sie dies einmal als generisch: interface Page<T> { data: T[]; nextCursor: string | null }.

Eine kurze Checkliste

  1. Nehmen Sie eine reine Probe und überprüfen Sie sie.
  2. Erstellen Sie Schnittstellen mit dem JSON-to-TypeScript-Konverter.
  3. Umbenennen von Typen in die Domänensprache.
  4. Beheben Sie optionale gegen Nullfächer, wörtliche Verbindungen und ID-Typen.
  5. Ersetzen Sie gemischte Arrays durch diskriminierte Gewerkschaften.
  6. Hinzufügen von Laufzeitvalidierung für externe Daten.
  7. Wechseln Sie zur Schema-basierten Erzeugung, wenn ein OpenAPI- oder GraphQL-Schema vorhanden ist.

Diese Schritte dauern nur wenige Minuten pro Endpunkt und zahlen sich um ein Vielfaches in automatisch abgeschlossenen, sichereren Refaktoren und Bugs aus, die entdeckt werden, bevor sie die Benutzer erreichen.

Diese Seite wurde automatisch aus dem Englischen übersetzt. Wenn dir ein Fehler auffällt, sag uns bitte Bescheid.

Verwandte Ratgeber