JSON zu TypeScript
JSON einfügen und sofort TypeScript-Interfaces erhalten.
Anleitung
- Fügen Sie Ihr JSON in das linke Feld ein (Objekt oder Array).
- Klicken Sie auf Konvertieren: TypeScript-Interfaces erscheinen rechts.
- Passen Sie den Root-Namen an und schalten Sie Optionen nach Bedarf um.
- Klicken Sie auf Ausgabe kopieren, um den erzeugten Code zu kopieren.
Häufig gestellte Fragen
Werden verschachtelte Objekte unterstützt?
Ja. Jedes verschachtelte Objekt erhält sein eigenes benanntes Interface. Array-Elemente werden ebenfalls analysiert, um den Element-Typ zu bestimmen.
Was passiert mit gemischten Array-Typen?
Wenn ein Array Elemente unterschiedlicher Typen enthält, verwendet der Konverter einen Union-Typ (z. B. string | number).
Werden JSON-Arrays als Root unterstützt?
Ja. Wenn der Root-Wert ein Array ist, analysiert der Konverter dessen Elemente und erzeugt das passende Interface plus einen Typ-Alias für das Array.
Was der Konverter tatsächlich tut
Er parst Ihr JSON, durchläuft jeden Wert und gibt eine Reihe von TypeScript-interface-Deklarationen aus, die die Struktur beschreiben. Verschachtelte Objekte erhalten jeweils ihr eigenes benanntes Interface, abgeleitet vom übergeordneten Eigenschaftsschlüssel in PascalCase (ein user-Feld wird zu einem User-Interface). Wenn zwei verschachtelte Objekte beim Namen kollidieren, erhält das zweite ein numerisches Suffix (User, User2). Auf der Wurzelebene wird ein Array zu einem Alias type Root = RootItem[]; plus dem RootItem-Interface; ein Objekt wird zu einem einzigen Root-Interface (oder welchen Namen Sie auch immer in das Feld „root name“ eingeben).
Beispiel-Ein- und -Ausgabe:
// Input
{
"id": 42,
"name": "Ada",
"active": true,
"tags": ["admin", "billing"],
"profile": { "bio": "Programmer", "link": null }
}
// Output
export interface Root {
id: number;
name: string;
active: boolean;
tags: string[];
profile: Profile;
}
export interface Profile {
bio: string;
link: unknown;
}
Die Typzuordnung von JSON → TypeScript
| JSON-Wert | Generiertes TS |
|---|---|
"hello" | string |
42 oder 3.14 | number (TS hat keinen separaten Ganzzahltyp) |
true / false | boolean |
null | unknown (der Konverter kann nicht erkennen, ob das Feld nullable ist oder in dieser Probe nur fehlt) |
[] | unknown[] |
[1, 2, 3] | number[] |
[1, "x"] | (number | string)[] |
{ "a": 1 } | benanntes interface |
Bei Objekt-Arrays auf Wurzelebene führt der Konverter die Schlüssel aller Elemente zu einem einzigen repräsentativen Interface zusammen. Das ist eine faire Näherung, wenn die Elemente dieselbe Struktur haben, verliert aber Informationen, wenn die Strukturen tatsächlich voneinander abweichen (z. B. ein heterogenes Events-Array). In diesem Fall müssten Sie nach der Generierung von Hand eine diskriminierte Union schreiben.
Warum interface für Objekte, type für das Wurzel-Array
Das offizielle TypeScript-Handbuch gibt eine einzeilige Faustregel: „Wenn Sie eine Faustregel möchten, verwenden Sie interface, bis Sie Funktionen von type benötigen.“ Beide sind strukturell typisiert, beide können Objektstrukturen beschreiben, aber interface gewinnt bei Objektstrukturen, weil es Deklarationszusammenführung unterstützt (das Interface erneut öffnen, um Felder hinzuzufügen), sauber mit extends funktioniert und in Compiler-Fehlern namentlich auftaucht. type-Aliase sind erforderlich, wenn Sie Unions von Primitiven, Schnittmengen mehrerer Typen oder die Benennung eines Nicht-Objekts brauchen, weshalb das Array auf Wurzelebene einen Alias type Root = RootItem[]; erhält statt eines Interfaces.
Ein Hinweis zur Benennung: Der Konverter verwendet PascalCase ohne das veraltete Präfix I (also User statt IUser). Moderne TS-Styleguides (von Google, Microsoft, der React-Community) lassen das Präfix nahezu durchgängig weg. Eigenschaftsnamen entsprechen genau den JSON-Schlüsseln (camelCase, wenn das JSON camelCase verwendet, snake_case, wenn es snake_case verwendet). Schlüssel, die keine gültigen JS-Bezeichner sind (mit Bindestrichen, Leerzeichen oder mit einer Ziffer beginnend), werden in Anführungszeichen gesetzt: "foo-bar": string;.
Was dieses Werkzeug nicht tut (ehrlich zu den Grenzen)
Ein einzelnes JSON-Beispiel trägt weniger Informationen als ein echtes Schema, daher sind mehrere Dinge, die schön zu erkennen wären, allein aus der Eingabe nicht möglich:
- Optionale Felder. Jede Eigenschaft in Ihrem Beispiel wird zur Pflicht. Wenn die echte API ein Feld manchmal weglässt, müssen Sie das
?von Hand hinzufügen:email?: string;. Oder lassen Sie den Konverter über mehrere Beispiele laufen und vereinigen Sie die Ergebnisse. - Erkennung von Nullable. Ein
nullim Beispiel wird zuunknown; der Konverter kann nicht wissen, ob das Feld wirklich nullable ist (string | null) oder in dieser Probe nur zufällig null war. Passen Sie es von Hand anhand des API-Vertrags an. - String-Literal-Unions. Ein Statusfeld mit dem Wert
"active"wird zustring, nicht zu"active" | "inactive" | "pending". Der Konverter kann die anderen Werte nicht sehen. - Erkennung des Datumstyps. Ein ISO-8601-String wie
"2024-04-12T10:00:00Z"bleibtstring. JavaScriptsDateist kein JSON-Typ. - Diskriminierte Unions. Wenn ein Wurzel-Array Elemente unterschiedlicher Struktur enthält (Events verschiedener Typen, polymorphe Datensätze), führt der Konverter alle Schlüssel zu einem Interface zusammen, statt eine getaggte Union zu erzeugen. Für echte heterogene Daten möchten Sie die Union von Hand schreiben.
- Zahlengenauigkeit. JavaScripts
numberstellt Ganzzahlen bis 253−1 sicher dar. Größere Ganzzahl-IDs verlieren an Genauigkeit, wenn sie vonJSON.parsegeparst werden; wenn Ihre API 64-Bit-Ganzzahlen zurückgibt, ist das sicherste Muster, sie als Strings zu senden und alsstringzu typisieren.
Wann dieses Werkzeug zu verwenden ist
- Typen aus einer echten API-Antwort heraus aufsetzen. Rufen Sie den Endpunkt auf, fügen Sie das JSON ein, erhalten Sie einen Startsatz von Interfaces. Passen Sie von Hand für optionale Felder und String-Literale an.
- Typen zu einem untypisierten Drittanbieter-SDK hinzufügen. Viele ältere JS-Bibliotheken werden ohne Typen ausgeliefert. Aus einer Beispielantwort zu generieren ist schneller, als die Dokumentation zu lesen.
- Typen zwischen Frontend und Backend teilen. Generieren Sie aus einem kanonischen Beispiel und kopieren Sie in beide Codebasen (oder teilen Sie über ein veröffentlichtes Typen-Paket).
- Eine JS-Codebasis zu TypeScript migrieren. Generieren Sie Typen aus echten Daten, die durch die App fließen, und annotieren Sie schrittweise Funktionssignaturen.
- Typen für eine Konfigurationsdatei generieren. Strenge Typisierung macht Konfigurationsfehler zur Kompilierzeit sichtbar.
- Die Struktur einer internen Datendatei dokumentieren. Das generierte Interface dient zugleich als maschinenlesbare Dokumentation.
Code-First vs. Schema-First vs. Direkt (wo dieses Werkzeug steht)
Drei gängige Arbeitsabläufe, um TypeScript-Typen aus Laufzeitdaten zu gewinnen:
- Code-First-Laufzeitvalidatoren: Zod, Yup, Effect Schema, Joi. Sie schreiben ein Validator-Schema in JS, es liefert Ihnen sowohl Laufzeit-Parsing als auch einen TypeScript-Typ per Inferenz. Das Schema ist die maßgebliche Quelle. Am besten, wenn die Validierung genauso wichtig ist wie der Typ.
- Schema-First: Schreiben Sie ein JSON Schema oder eine OpenAPI-Spezifikation, generieren Sie TypeScript-Typen mit Werkzeugen wie
quicktype,json-schema-to-typescriptoderopenapi-typescript. Am besten, wenn ein API-Vertrag mehrere Sprachen umspannt. - Direkte Beispiel-Inferenz (dieses Werkzeug sowie der reine JSON-Modus von quicktype), echte Daten einfügen, Typen erhalten. Schnellster Weg; schwächste Validierungsgarantien, weil nichts die Laufzeitdaten gegen den Typ prüft.
Die richtige Wahl hängt davon ab, ob es Ihnen hauptsächlich um statische Typprüfung geht (dieses Werkzeug ist großartig) oder auch um Laufzeitsicherheit (greifen Sie dann zu Zod / Effect Schema).
Häufige Fehler
- Generierte Typen als fertige Spezifikation behandeln. Sie sind ein zu 70 % fertiger Ausgangspunkt. Fügen Sie
?für optionale Felder hinzu,| nullwo wirklich nullable, String-Literal-Unions wo zutreffend. - Aus einem einzigen Beispiel generieren, wenn die API Varianten hat. Ein Benutzerobjekt, das manchmal eine
emailhat und manchmal nicht, wird als „email ist erforderlich“ generiert. Lassen Sie mehrere Beispiele laufen und vereinigen Sie die Ergebnisse oder bearbeiten Sie von Hand. - Alles automatisch als
readonlymarkieren. Nützlich für unveränderliche Datenflüsse, aber falsch für Zustandsobjekte, die Sie verändern. Verwenden Sie denreadonly-Schalter mit Bedacht. - Der Genauigkeit bei großen Ganzzahl-IDs vertrauen. JavaScripts
numberendet bei 253−1. Für 64-Bit-IDs als Strings übertragen und alsstringtypisieren. interfacemittypeverwechseln. Unterschiedliche Werkzeuge, unterschiedliche Kompromisse. Die Faustregel des TypeScript-Handbuchs lautet „verwende interface, sofern du nicht eine Funktion brauchst, die nur type bietet“. Genau das tut dieses Werkzeug.- Vertrauliches JSON in einen serverseitigen Konverter einfügen. Echte API-Antworten enthalten oft Kundendaten, Zugangsdaten, interne IDs. Die rein browserbasierte Umwandlung (dieses Werkzeug) behält die Daten auf Ihrem Rechner.
Weitere häufig gestellte Fragen
Warum wurden alle meine Felder als erforderlich markiert?
Weil ein einzelnes JSON-Beispiel dem Konverter nicht sagen kann, welche Felder in der echten API manchmal fehlen. Jeder Schlüssel, der im Beispiel vorkommt, wird zur Pflicht. Wenn Sie wissen, dass ein Feld optional ist, fügen Sie von Hand ein abschließendes ? hinzu: email?: string;. Für die Erkennung von Optionalität über mehrere Beispiele hinweg beherrscht das ausgefeiltere quicktype-CLI dies nativ.
Warum ist mein Null-Feld als unknown typisiert?
Weil der Konverter aus einem einzelnen null nicht erkennen kann, ob das Feld immer nullable ist (string | null) oder ob es in dieser Probe nur zufällig null war (string). unknown ist der konservative Standard; TypeScript zwingt Sie, den Typ einzugrenzen, bevor Sie den Wert verwenden, was sicherer ist als any. Bearbeiten Sie es von Hand zu string | null, sobald Sie die Absicht der API kennen.
Sollte ich interface oder type verwenden?
Die Faustregel des offiziellen TypeScript-Handbuchs: Verwenden Sie interface, bis Sie eine Funktion brauchen, die nur type bietet, vor allem Union-Typen, Schnittmengen-Typen oder die Benennung eines Primitivs. Dieser Konverter folgt dieser Regel: interface für jede Objektstruktur, type für den Wurzel-Array-Alias. Einige Styleguides empfehlen, stattdessen standardmäßig type zu nehmen (Matt Pocock hat öffentlich dafür argumentiert), aber der übliche Standard ist interface für Objekte.
Wird mein JSON irgendwohin hochgeladen?
Nein. Die Umwandlung ist eine eigenständige JavaScript-IIFE, die Ihr JSON über JSON.parse parst, den Wert durchläuft und die TypeScript-Ausgabe in ein Textfeld schreibt. Es gibt keinen Fetch, keinen Analyse-Aufruf, der den JSON-Inhalt überträgt, keinen Server. Das ist wichtig, weil echte API-Antworten typischerweise Kundendaten, interne IDs oder Zugangsdaten enthalten, die Sie nicht durch einen Dritten leiten möchten.
Was ist mit JSDoc, Zod oder Laufzeitvalidierung?
Dieses Werkzeug gibt nur TypeScript-Typen zur Kompilierzeit aus: keine Laufzeitvalidatoren (kein Zod / Yup / Effect Schema), keine JSDoc-Kommentare. Wenn Sie Laufzeitvalidierung benötigen, die zugleich als statischer Typ dient, schreiben Sie das Schema in Zod und verwenden Sie Zods z.infer<typeof Schema>, um den Typ abzuleiten. Wenn Sie ein JSON Schema haben und sowohl Laufzeitvalidierung als auch TS-Typen möchten, ist json-schema-to-typescript + AJV die übliche Kombination.
Warum gibt es kein I-Präfix bei den Interface-Namen?
Weil die meisten modernen TypeScript-Styleguides es weglassen. Googles TypeScript Style Guide rät ausdrücklich davon ab; die React-Community hat sich auf PascalCase ohne Präfix geeinigt. Die veraltete IUser-Konvention kam vom Einfluss von C# / Java auf frühes TypeScript; aktuelle Praxis ist schlicht User.