HandyTools Hub

JSON zu TypeScript

TypeScript-Interfaces sofort aus JSON-Daten generieren

Deklarationsart
Das generierte TypeScript erscheint hier...

Der JSON-zu-TypeScript-Konverter liest eine JSON-Stichprobe und gibt direkt nutzbare Typdeklarationen aus. Verschachtelte Objekte werden eigene benannte Interfaces, Arrays werden zu einem einheitlichen Elementtyp zusammengeführt, und identische Objektformen werden wiederverwendet statt dupliziert. Alles läuft beim Tippen im Browser mit einer kurzen Verzögerung, Sie können also eine echte API-Antwort einfügen und das Ergebnis direkt in Ihr Projekt kopieren.

So funktioniert die Inferenz

Das Werkzeug parst den Text mit JSON.parse. Schlägt das fehl, zeigt es die Meldung des Parsers und stoppt. Bei Erfolg durchläuft es den Wert rekursiv:

  • ein String wird zu string, eine Zahl zu number, ein Boolean zu boolean, und null und undefined werden beide zu any;
  • ein Objekt wird zu einer benannten Deklaration, und seine Eigenschaftsnamen werden für diesen Namen in PascalCase umgewandelt;
  • ein Array untersucht jedes Element, sammelt die unterschiedlichen Elementtypen und verbindet sie mit |.

Namen werden aus dem Eigenschaftspfad abgeleitet. Ein Schlüssel wie shipping_address oder shipping-address ergibt beide ShippingAddress. Ist ein Name bereits durch eine andere Form belegt, hängt das Werkzeug 2, dann 3 und so weiter an. Zwei Objekte mit exakt denselben Eigenschaftsnamen, Typen und Optionalitäten teilen sich eine Deklaration, eine wiederholte Form wird also nur einmal ausgegeben.

Die Umwandlung ist um etwa 300 Millisekunden entprellt, die Deklarationen stehen also kurz nachdem Sie mit Tippen aufhören fest, statt bei jedem Tastendruck. Der Wurzelname durchläuft dieselbe PascalCase-Umwandlung wie jeder andere Bezeichner: Eine Wurzel namens order response wird zu OrderResponse, und dieser Name bestimmt die oberste Deklaration sowie die abgeleiteten Namen der verschachtelten Typen.

Praxisbeispiel: Eine API-Antwort

Gegeben sei diese Eingabe:

{
  "id": 1,
  "name": "Ada",
  "tags": ["math", "code"],
  "address": { "city": "London", "zip": "E1" }
}

Die Ausgabe lautet:

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

export interface Address {
  city: string;
  zip: string;
}

Das Wurzelobjekt erscheint immer zuerst, gefolgt von den verschachtelten Deklarationen in der Reihenfolge ihrer Entdeckung. tags ist ein homogenes Array und wird zu string[]; address wird zu einer Referenz auf sein eigenes Interface.

Umgang mit Arrays und optionalen Schlüsseln

Ein Array von Objekten wird zu einem Interface verschmolzen. Jeder Schlüssel erscheint einmal, und jeder Schlüssel, der in mindestens einem Element fehlt, wird als optional markiert. Zum Beispiel:

{ "users": [
  { "id": 1, "email": "a@example.com" },
  { "id": 2, "name": "Bob" }
] }

ergibt:

export interface Root {
  users: Users[];
}

export interface Users {
  id: number;
  email?: string;
  name?: string;
}

Das Element-Interface heißt Users, weil es vom Schlüssel users abgeleitet ist. Haben Elemente widersprüchliche Typen für denselben Schlüssel, werden diese Typen zu einer Union verbunden, ein Feld, das in einem Objekt eine Zahl und in einem anderen ein String ist, wird also zu number | string. Ein gemischtes primitives Array wie [1, "two"] wird zu (number | string)[], während [1, 2, 3] als number[] bleibt.

Eigenschaftsnamen, die keine gültigen JavaScript-Bezeichner sind, werden mit JSON.stringify in Anführungszeichen gesetzt, ein Schlüssel wie "first-name" wird also als "first-name": string; ausgegeben.

interface oder type

Der Deklarationsumschalter ändert die Syntax, nicht die abgeleitete Struktur. Im Modus interface schreibt das Werkzeug export interface Name { ... }, im Modus type schreibt es export type Name = { ... };. Interfaces unterstützen Declaration Merging und sind die übliche Wahl für Objektformen; Typ-Aliase sind gleichförmiger, wenn Sie sie später mit Unions kombinieren möchten. Das export-Kästchen fügt lediglich das Präfix export hinzu oder entfernt es, was praktisch ist, wenn Sie in eine Datei einfügen, die diese Namen bereits importiert.

Eine Konsequenz des Umschalters ist wissenswert: Ein Wurzel-Array erzeugt unabhängig von der Einstellung immer einen Typ-Alias, weil ein Array keine Objektform ist. Selbst im interface-Modus sehen Sie eine einzelne Zeile type Root = RootItem[];, kombiniert mit einem Interface für die Elementform.

Grenzen der Genauigkeit

  • null und undefined fallen zu any zusammen, nullable-Felder verlieren dadurch ihre Absicht.
  • Ein leeres Array wird zu any[], was erlaubend statt präzise ist.
  • Eine skalare Wurzel wie "hello" oder [1, 2, 3] wird als Typ-Alias ausgegeben, nicht als Interface.
  • Nur Arrays offenbaren Optionalität. Ein in der Stichprobe fehlendes Feld wird nicht als optional markiert.
  • Ganzzahlen und Dezimalzahlen werden beide zu number; es gibt keinen bigint-, Date- oder Dezimaltyp.
  • String-Werte werden nicht zu Literal-Unions, "active" wird also als string typisiert.
  • Die Ausgabe ist nur zur Kompilierzeit gültig und führt keine Laufzeitvalidierung durch.

Praxistipps

Fügen Sie die vollständigste Antwort ein, die Sie haben, idealerweise eine, die optionale Felder und jede Array-Variante abdeckt. Schicken Sie das JSON zuerst durch einen Formatierer, wenn es minifiziert angekommen ist, denn der Konverter zeigt den Parserfehler wörtlich an. Halten Sie den Wurzelnamen aussagekräftig (UserResponse, Order), weil jedes verschachtelte Interface daraus benannt wird. Sind die abgeleiteten Typen zu locker, bearbeiten Sie einzelne Felder von Hand, um Literal-Unions oder Nullbarkeit hinzuzufügen; der erzeugte Code ist ein Ausgangspunkt, kein Vertrag.

Achten Sie auf versehentliches Teilen von Formen. Haben zwei unabhängige verschachtelte Objekte zufällig dieselben Feldnamen, Typen und Optionalitäten, werden sie zu einer Deklaration verschmolzen. Das ist meist gewünscht, bedeutet aber, dass der geteilte Typ für beide Aufrufstellen gültig bleiben muss; benennen Sie einen Schlüssel um oder teilen Sie die Stichprobe, wenn sich die beiden Formen unabhängig entwickeln sollen.

Verwandte Tools

  • JSON Formatter — JSON vor der Umwandlung formatieren, validieren und verschönern.
  • JSON Schema Generator — ein JSON Schema aus Ihren Daten für die Laufzeitvalidierung ableiten.
  • YAML Converter — YAML-Konfigurationen zuerst nach JSON umwandeln, dann Typen erzeugen.

Häufig gestellte Fragen

Warum wurde mein JSON-null zu any statt zu null?

Das Werkzeug bildet null und undefined beide auf any ab, weil eine einzelne Stichprobe nicht erkennen lässt, ob ein Feld immer null ist oder nur in dieser einen Antwort. Wenn Sie eine ausdrückliche Null-Behandlung wünschen, ändern Sie die erzeugte Deklaration von Hand zu `string | null` oder einer ähnlichen Union, die das Werkzeug nicht ableiten kann.

Wie entscheidet der Generator, dass eine Eigenschaft optional ist?

Nur Arrays lehren ihn Optionalität. Wird ein Array von Objekten zu einem Interface verschmolzen, erhält jeder Schlüssel, der in mindestens einem Element fehlt, ein Fragezeichen. In einem einfachen Objekt gilt jeder Schlüssel als erforderlich, weil es in der Eingabe kein Gegenbeispiel gibt.

Was macht das Werkzeug mit einem leeren Array?

Ein leeres Array hat keine Elemente zum Untersuchen, deshalb gibt das Werkzeug any[] aus. Das ist ein Signal, den Typ von Hand zu füllen, da eine spätere nicht leere Antwort sonst stillschweigend akzeptiert würde. Fügen Sie eine repräsentative Stichprobe mit mindestens einem Element ein.

Leitet es String-Literal-Unions wie „active“ | „paused“ ab?

Nein. Ein JSON-String wird stets als der breite Typ string abgeleitet, eine Zahl als number. Literal-Unions, Enums, gebrandete IDs und Datumsstrings erfordern alle eine manuelle Anpassung, weil die Ableitung aus einem einzigen Wert nicht beweisen kann, dass andere Werte unmöglich sind.

Warum wird mein Wurzel-Array als type Root = Items[] statt als Interface deklariert?

Ein Interface beschreibt die Form eines Objekts, hier ist die Wurzel aber ein Array, deshalb gibt das Werkzeug einen Typ-Alias aus. Es benennt zudem das Element-Interface nach der Wurzel mit dem Suffix Item, etwa RootItem, damit Alias und Elementtyp nie kollidieren.

Kann ich die Ausgabe direkt mit Zod oder io-ts zur Laufzeitvalidierung nutzen?

Nein. Der Generator erzeugt einfache TypeScript-Deklarationen, die nur zur Kompilierzeit existieren und aus dem laufenden JavaScript entfernt werden. Kombinieren Sie die Ausgabe mit einer Schema-Bibliothek zur Laufzeit, wenn Sie fehlerhafte Daten zur Laufzeit abweisen müssen.

Geprüft vom HandyTools-Hub-Team · Zuletzt aktualisiert