§

JSON-Beispiel

Typ-Inferrer wird vorbereitet…
§

TypeScript-Interfaces

TypeScript

TypeScript-Teams stoßen früh auf dieses Problem. Die großen SDKs liefern typisierte Clients (Stripe, Twilio, AWS), aber interne Dienste und Webhook-Payloads von Drittanbietern tun das selten. Der typische Workflow lautet: eine echte Antwort im Netzwerk-Panel erfassen, hier einfügen, die Wurzel nach dem Endpunkt benennen und die Ausgabe in das Types-Verzeichnis des Projekts kopieren. Von dort aus erkennt der Strict-Modus die Abweichungen, die die Dokumentation vergessen hat zu erwähnen. SAP-Entwickler, die BTP-Microservice-Grenzen typisieren, und Teams, die BSI-Grundschutz-konforme Schnittstellen für Behördenanwendungen absichern, nutzen die inferierten Formen zur JSON-Validierung an Dienstgrenzen, ohne eine Laufzeit-Schema-Abhängigkeit ins Bundle hinzuzufügen. Der Inferrer läuft vollständig in deinem Browser, sodass Payloads von Staging-APIs, signierten Webhook-Bodys und unveröffentlichten Endpunkten nie einen gehosteten Dienst erreichen.

Wie JSON-zu-TypeScript-Inferenz funktioniert

Die Inferenz ist ein einziger Durchlauf über den geparsten JSON-Baum. Das Tool liest jeden Wert, wählt einen TypeScript-Typ dafür aus und schreibt dann ein Interface pro gefundenem Objekt aus.

  1. Das JSON-Beispiel mit dem nativen Parser des Browsers parsen und fehlerhafte Eingaben mit einem Zeilen-/Spalten-Hinweis ablehnen.
  2. Einen TypeScript-Typ für jeden Wert ermitteln — string, number, boolean, null, Array oder verschachteltes Objekt.
  3. Jedem verschachtelten Objekt einen vom übergeordneten Property-Key abgeleiteten Interface-Namen geben (sodass user.address zu einem Address-Interface wird).
  4. Item-Typen über jedes Array zusammenführen, sodass eine Liste aus {id: 1} und {id: 2, label: "x"} einen Union mit den richtigen optionalen Feldern ergibt.
  5. Die Optionen anwenden (interface vs. type, readonly, optional-nullable) und Deklarationen in Abhängigkeitsreihenfolge ausgeben, sodass die Datei ohne Forward-Referenzen kompiliert.

Warum TypeScript-Typen aus JSON generieren?

  • Die meisten Formfehler lassen sich zur Kompilierzeit erkennen, wenn der Antworttyp aufgeschrieben ist. Ein Interface aus einer echten Payload zu inferieren schreibt den Großteil davon, und der Strict-Modus erkennt das Feld, das die Dokumentation vergessen hat zu erwähnen.
  • Das Pairing inferierter Interfaces mit einem Laufzeit-Validator wie Zod oder io-ts gibt derselben Form zwei Aufgaben: Editor-Autocomplete in der Entwicklung und einen 400-Fehler am Rand, wenn die Produktion etwas Unerwartetes sendet.
  • TypeScript's Language Server zeigt nur Felder an, die er kennt. Sobald du das inferierte Interface importierst, funktioniert Autocomplete in dem Moment, wo du den Punkt tippst — kein as any-Cast auf der Antwort und kein frustriertes Grep durch das Repo mehr.
  • Wenn du im Begriff bist, eine OpenAPI-Spezifikation zu schreiben, ist ein inferiertes Interface ein schneller erster Entwurf des Antwort-Schemas. Du wirst noch handgeschriebene Beispiele und Constraints brauchen, aber die Eigenschaftsnamen und Typen sind bereits korrekt.

Häufige Anwendungen

Inferenz hilft am meisten, wenn eine echte Payload vorhanden ist, aber kein Schema.

  • Typisierung von Webhook-Payloads von Drittanbietern wie Stripe, GitHub oder Twilio vor dem Schreiben eines Handlers.
  • Typen für eine interne REST-API bootstrappen, damit das Frontend-Team noch am selben Tag mit dem Entwickeln dagegen beginnen kann, an dem das Backend landet.
  • Einen Ausgangspunkt für ein Zod-, io-ts- oder Valibot-Schema aus einer beobachteten API-Antwort generieren.

Wie sieht die Ausgabe aus?

Gegeben ein JSON-Beispiel und ein Wurzelname erzeugt der Generator einen Interface-Baum, ein Interface pro verschachteltem Objekt. Für die folgende Eingabe mit Wurzelname User:

Füge {"id":1,"name":"Alice","tags":["a","b"],"address":{"city":"Paris"}} mit Wurzelname User ein und der Generator erzeugt:

export interface User {
  id: number;
  name: string;
  tags: string[];
  address: Address;
}

export interface Address {
  city: string;
}
Beachte, dass address zu einem eigenen benannten Interface befördert wurde — das ist die abhängigkeitsgeordnete Ausgabe. Dasselbe JSON mit dem Deklarationsstil type würde export type User = {...} ausgeben; mit aktiviertem Readonly-Schalter erhält jede Eigenschaft den readonly-Modifikator.

Generator-Optionen

Deklarationsstil

Wähle interface (der TypeScript-Standardidiom für Objektformen) oder type (praktisch, wenn du später Mapped Types, Conditional Types oder Intersections benötigst). Beide erzeugen identisches Laufzeitverhalten; die Wahl ist eine Coding-Style-Präferenz.

Optionale Nullable-Felder

Wenn ein gesampelter Wert null ist, wird der Typ des Felds zu T | null. Diese Option aktivieren fügt zusätzlich einen ?-Modifikator hinzu, sodass das Feld auf der TypeScript-Seite optional ist — nützlich, wenn die API den Schlüssel manchmal ganz weglässt statt null zurückzugeben.

Readonly-Modifikator

Stellt jeder Eigenschaftsdeklaration readonly voran, sodass das ausgegebene Interface einem unveränderlichen Datenmodell entspricht. Praktisch für Redux-State-Slices, eingefrorene API-Antworten oder überall dort, wo der Compiler unbeabsichtigte Mutationen kennzeichnen soll.

Unterstützt das verschachtelte Objekte und Arrays?

Ja. Jedes verschachtelte Objekt wird zu einem benannten Interface, das vom übergeordneten Property-Key abgeleitet ist, und Arrays inferieren den Item-Typ aus ihrem Inhalt. Arrays von Objekten erhalten ein Interface pro Objektform, mit Union-Typen, wo die Formen abweichen.

Wie werden optionale Felder inferiert?

Aktiviere den Schalter "Nullable-Felder als optional markieren" und jedes Feld, dessen gesampelter Wert null ist, erhält einen ?-Modifikator am Schlüssel plus | null im Typ. Ohne den Schalter bleibt das Feld required und der Typ ist nur T | null.

Unterstützt das diskriminierte Unions?

Grundlegende Union-Typen entstehen, wenn ein Array Elemente mit gemischten Formen enthält oder wenn ein Feld sowohl einen Wert als auch null trägt. Vollständige diskriminierte Union-Inferenz (Auswahl von type oder kind als Tag und Aufteilen der Varianten) benötigt mehrere Beispiele — das ist geplant, aber nicht im aktuellen Build.

Kann ich Typen aus mehreren JSON-Beispielen inferieren?

Noch nicht — der aktuelle Inferrer liest jeweils ein Beispiel. Wenn du zwei Payloads hast, die sich ein Interface teilen sollen (z. B. ein Listen-Endpunkt und ein Einzelelement-Endpunkt), besteht die praktische Umgehung darin, sie in ein Array zusammenzuführen, daraus zu generieren und dann die entstehenden Union-Typen umzubenennen. Mehrstichproben-Inferenz ist auf der Roadmap, da es der einzige Weg ist, Felder zu erkennen, die in einer Antwort vorhanden und in einer anderen abwesend sind.

Payload einfügen, Wurzel benennen, Interfaces kopieren. Die gesamte Pipeline läuft in deinem Browser, sodass eine unveröffentlichte API oder ein signierter Webhook-Body auf deinem Gerät bleibt.