Zum Hauptinhalt springen

JSON in TypeScript umwandeln

Dieses Tool erzeugt aus einem Beispieldokument in Ihrem Browser Interfaces. Fügen Sie alle Datensätze ein, die Sie haben, nicht nur einen: Ein Feld, das in manchen Datensätzen vorkommt und in anderen nicht, ist nur über mehrere Beispiele erkennbar – und wird dann ein optionales Member statt einem Pflichtmember, das zur Laufzeit fehlt.

Nur lokal
Struktur
Beispiel-JSON
0 B1 ZeileZ. 1, Sp. 1
Syntaxfehler · Fehler in Zeile 1, Spalte 1

Das Dokument endet zu früh – es scheint abgeschnitten.


^
Generierter Codeschreibgeschützt
0 B1 Zeile
Fügen Sie nach Möglichkeit mehrere Datensätze ein. Nur so werden optionale Felder erkannt, die nicht in jeder Zeile vorkommen.

Wie funktioniert JSON in TypeScript umwandeln?

Der Generator baut aus Ihrem Beispiel ein einziges Zwischenmodell der Typen und rendert es dann – klingt nach einem Implementierungsdetail und ist der Grund, warum die Ausgabe korrekt ist. Die wirklich harten Entscheidungen – ist dieses Feld optional, sind diese beiden Objekte derselbe Typ, was ist der Elementtyp eines gemischten Arrays – werden einmal an einer Stelle beantwortet, statt bei jedem Wert neu abgeleitet zu werden.

Optionale Felder entstehen aus Widersprüchen zwischen Datensätzen

Bei [{"a":1}, {"a":1,"b":2}] liest die naheliegende Implementierung das erste Element und erzeugt { a: number } – b geht stillschweigend verloren. Die richtige Antwort vereint die Feldmengen aller Elemente: a ist in beiden, also Pflicht; b ist in einem, also b?: number. Das ist der mit Abstand größte Unterschied zwischen Generatoren und der Grund, warum das Einfügen eines einzelnen Datensatzes einen Typ erzeugt, der einen Datensatz beschreibt und nicht Ihre API.

Identische Formen werden zu einem Typ, nicht zu fünfzig

Jedes Objekt bekommt einen Fingerabdruck über seine Struktur – Schlüsselnamen, Optionalität und der Fingerabdruck jedes Wertetyps, unabhängig von der Reihenfolge. Ein Dokument mit fünfzig Kunden, die jeweils eine Adresse derselben Form haben, erzeugt ein einziges Address-Interface statt Address bis Address50. Die Namen stammen aus dem Schlüssel, der das Objekt enthielt, im Singular, wenn er ein Array enthielt: "users": [{…}] erzeugt User.

null ist Nullbarkeit, kein Typ

Ist ein Feld in einem Datensatz eine Zahl und in einem anderen null, ist die Ausgabe number | null statt eines Union-Typs mit generiertem Namen. Ist ein Feld in allen Datensätzen null, ist die ehrliche Antwort unknown mit einem Kommentar, der das sagt – null auszugeben wäre über Ihr Beispiel korrekt und über Ihre Daten nutzlos.

Zahlen sind Zahlen, mit einem Hinweis

TypeScript hat einen einzigen Zahlentyp, daher werden Ganzzahlen und Gleitkommazahlen beide zu number. Eine Ganzzahl, die zu groß für einen 32-Bit-Typ ist, wird trotzdem in einem Kommentar markiert, denn dasselbe Modell steckt auch hinter den Go-, Java- und C#-Generatoren, wo diese Unterscheidung über int oder int64 entscheidet – und weil es gut zu wissen ist, wenn überhaupt eine 64-Bit-ID in JavaScript ankommt.

Beispiel

[
  { "id": 1, "name": "Ada", "deleted_at": null },
  { "id": 2, "name": "Grace", "deleted_at": null, "team": "ops" }
]

Generiert

export interface User {
  id: number;
  name: string;
  deleted_at: unknown; // only null in the sample
  team?: string;
}

Welche Optionen und Sonderfälle unterstützt JSON in TypeScript umwandeln?

Technische Referenz und Optionen
ParameterTypStandardVerhalten & Sonderfälle
WurzeltypBezeichnerRootName für den Top-Level-Typ. Ein Array-Root wird als Name[] berichtet, und Objektformen innerhalb davon werden nach den Schlüsseln benannt, die sie enthalten.
interface / typeDeklarationinterfaceSchnittstellen unterstützen Deklarationsvereinheitlichung und erzeugen bessere Fehlermeldungen bei Objektformen; Typaliase sind erforderlich, wenn Sie später Vereinigungen oder gemappte Typen benötigen. Beides ist hier gültig.
readonlyBooleschoffMarkiert jedes Mitglied als readonly. Es lohnt sich, dies für einen analysierten API-Antwort zu aktivieren, die nichts in Ihrem Code an Ort und Stelle verändern sollte.
camelCase-SchlüsselBooleschoffBenennt snake_case-Schlüssel um und zeichnet das Original in einem nachfolgenden Kommentar auf. Nur korrekt, wenn in Ihrer Pipeline tatsächlich etwas sie umbenennt – der generierte Typ stimmt sonst nicht mehr mit der JSON überein.
Optionalitäterschlossenüber alle DatensätzeEin Schlüssel, der in mindestens einem Datensatz derselben Form fehlt, wird optional. Fügen Sie mehrere Datensätze ein; ein einzelner Datensatz kann dies nicht ausdrücken.
NullableerschlossenVereinigung mit nullEin Wert, der in einigen Datensätzen null und in anderen ein String ist, wird zu string | null. Fehlend und null sind unterschiedliche Dinge und werden unterschiedlich berichtet.
Gemischte ArraysVereinigunggeklammertEin Array gemischter Skalare wird zu (string | number)[]. Die Klammern sind wichtig: string | number[] bedeutet etwas völlig anderes.
Eingabegrößebytes2 MBDie Inferenz liest jeden Wert. Ein paar hundert repräsentative Datensätze beschreiben eine Form ebenso gut wie eine Million, also ist die Obergrenze in der Praxis ohne Kosten.

Häufig gestellte Fragen

Warum ist ein Feld optional, obwohl meine API es immer sendet?

Weil mindestens ein Datensatz in dem Beispiel, das Sie eingefügt haben, es nicht hatte. Der Generator kann nur die Daten beschreiben, die er bekommen hat. Ist das Feld wirklich immer vorhanden, fügen Sie ein Beispiel ein, in dem es immer auftaucht – oder entfernen Sie das ? von Hand; das ist richtig, wenn Sie den Vertrag besser kennen als das Beispiel.

Sollte ich einen Datensatz einfügen oder die ganze Antwort?

Die ganze Antwort, idealerweise mehrere. Optionalität, Nullbarkeit und gemischte Typen sind Eigenschaften der Gesamtheit der Datensätze, nicht eines einzelnen. Ein Generator, der nur einen Datensatz bekommt, kann ein immer vorhandenes Feld nicht von einem unterscheiden, das diesmal zufällig da war – und erzeugt souverän einen Typ, der auf die Art falsch ist, die am schwersten zu bemerken ist.

Warum habe ich unknown statt eines echten Typs bekommen?

Jedes Beispiel an dieser Stelle war null, also gibt es nichts, woraus sich etwas ableiten ließe. Die Alternativen sind schlechter: null als Typ ist über das Beispiel korrekt und über die Daten nutzlos, und any schaltet die Typprüfung für alles Nachgelagerte ab. unknown zwingt Sie, vor der Verwendung einzugrenzen – genau das Richtige, wenn der Typ wirklich unbekannt ist.

Kann es Laufzeit-Validatoren erzeugen, nicht nur Typen?

Nein. TypeScript-Typen werden zur Kompilierzeit gelöscht; ein aus einem Beispiel erzeugtes Interface sagt Ihnen daher nichts über die Antwort, die Sie zur Laufzeit tatsächlich erhalten. Brauchen Sie die Garantie statt nur die Annotation, erzeugen Sie stattdessen ein JSON Schema und validieren Sie dagegen, oder schreiben Sie ein Zod-Schema von Hand. Ein generiertes Interface als Validierung zu behandeln, ist ein häufiger und teurer Fehler.

Beherrscht es tief verschachtelte oder rekursive Dokumente?

Verschachtelung ja, bis zu einer Tiefe von 100 – darüber hinaus wäre der generierte Code ohnehin unbenutzbar, also gibt es eine klare Obergrenze statt eines Stack-Overflows. Echte Rekursion (ein Kommentar, der Kommentare enthält) wird so weit abgeleitet, wie das Beispiel reicht; hat das Beispiel drei Ebenen, bekommen Sie drei Ebenen, denn nichts in den Daten sagt, dass die Struktur sich ewig wiederholt.

Wird mein JSON hochgeladen?

Nein. Inferenz und Rendern laufen beide in dem Tab, den Sie schon offen haben – öffnen Sie die DevTools und beobachten Sie beim Einfügen das Netzwerk-Panel. Das ist hier wichtiger als bei den meisten Tools, denn die Dokumente, die Leute umwandeln, sind API-Antworten aus der Produktion, oft mit echten Kundendatensätzen darin.