Zum Inhalt springen
jsonbeautifiers
Deutsch

JSON in TypeScript

Interfaces über alle Array-Elemente zusammengeführt, damit optionale Felder wirklich optional sind.

JSON
TypeScript

Nichts, was Sie einfügen, verlässt Ihren Browser. Die connect-src Erlaubnisliste macht daraus eine Garantie des Browsers statt eines Versprechens. Selbst überprüfen

Verwandeln Sie ein JSON-Payload in TypeScript-Interfaces. Verschachtelte Objekte werden zu eigenen benannten Typen, Arrays werden über alle Elemente zusammengeführt, und strukturell identische Formen werden einmal ausgegeben und wiederverwendet.

Aus einer Stichprobe zu schließen ist Raterei. Der Sinn dieser Seite ist, dass die Vermutungen sichtbar sind.

Optionale Felder - hier scheitern die meisten Generatoren

Ein Generator, der Element null eines Arrays liest und aufhört, erzeugt ein Interface, in dem jedes Feld verpflichtend ist. Der erste Datensatz, der ein optionales Feld auslässt, fällt dann durch die Typprüfung, und Sie bearbeiten die generierten Typen von Hand - womit der Zweck dahin ist.

Dieser hier führt alle Elemente zusammen. Ein Schlüssel, der in allen vorkommt, ist verpflichtend; einer, der nur in manchen vorkommt, wird mit einem Fragezeichen als optional markiert. Das ist echte Information aus Ihrer Stichprobe, die ein Ein-Element-Generator wegwirft.

Die übrigen Entscheidungen

Aus null wird eine Union
Ein Feld, das als Zeichenkette und als null gesehen wurde, ist string | null - nicht any und nicht string.
Ein leeres Array ist unknown[]
Nicht any[]. Ein leeres Array trägt keine Typinformation, und any[] würde die Prüfung für alles, was es berührt, klammheimlich abschalten.
Wiederholte Formen werden dedupliziert
Eine Liste mit fünfhundert Datensätzen erzeugt ein Interface, nicht fünfhundert.
Namen von Array-Elementen werden in den Singular gesetzt
Ein Array categories erzeugt ein Interface Category.
Ungültige Bezeichner werden quotiert
Ein Schlüssel has-dash, 2fast oder class wird zu einem Eigenschaftsnamen in Anführungszeichen.
Unsichere Ganzzahlen werden markiert
Ein Feld als number zu typisieren, während die Stichprobe eine Ganzzahl über 2^53-1 enthielt, ist eine Lüge, denn JavaScript kann sie nicht darstellen. Der Hinweis sagt das; die richtige Lösung liegt weiter oben, indem sie als Zeichenkette gesendet wird.

Was ein generierter Typ Ihnen nicht gibt

Ein TypeScript-Interface wird zur Laufzeit gelöscht. Es sagt dem Compiler, was Sie erwarten, und tut überhaupt nichts, wenn die API etwas anderes schickt. Dafür brauchen Sie einen Laufzeitvalidator, und der ehrliche Ablauf für eine externe API ist ein Schema, das validiert und den Typ aus derselben Definition ableitet.

Zod, Valibot und ArkType machen genau das. Erzeugen Sie hier ein Interface, um ein Payload zu verstehen, und schreiben Sie dann das Laufzeitschema für die Grenze, die Sie nicht kontrollieren.

How to do this in code

Dieselbe Idee im Code - und was man an einer Grenze nimmt, der man nicht traut.

sh quicktype

quicktype unterstützt viele Zielsprachen. Mehrere Stichproben zu übergeben ist die Option, auf die es ankommt.

npx quicktype --lang ts --just-types --src-lang json payload.json

# Several samples, which is what makes optionality accurate
npx quicktype --lang ts --just-types samples/*.json
ts Zod

Das ist das Muster für eine API-Grenze. Das Interface sagt es dem Compiler; das Schema sagt die Wahrheit.

import { z } from 'zod';

const User = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  verifiedAt: z.string().nullable(),
  roles: z.array(z.string()),
});

// One definition, both a runtime check and a static type
type User = z.infer<typeof User>;

const result = User.safeParse(await res.json());
if (!result.success) console.error(result.error.issues);
ts Nur Typen, aus einem Literal
// If the data is a constant you control, TypeScript can infer
// the type without a generator at all.
const config = {
  retries: 3,
  endpoints: ['a', 'b'],
} as const;

type Config = typeof config;

Häufige Fragen

Warum ist ein Feld optional, obwohl meine API es immer sendet?
Weil mindestens ein Datensatz in der Stichprobe es nicht hatte. Das ist entweder ein echtes optionales Feld oder eine unvollständige Stichprobe. Fügen Sie ein Array mit mehr Datensätzen ein, und die Antwort wird besser.
Soll ich interface oder type nehmen?
Für Objektformen macht es kaum einen Unterschied. Interfaces erlauben Declaration Merging und liefern etwas angenehmere Fehlermeldungen; Typaliase können Unions und Mapped Types ausdrücken. Oben stehen beide zur Wahl.
Validieren diese Typen irgendetwas zur Laufzeit?
Nein. TypeScript-Typen werden beim Kompilieren gelöscht. Sie beschreiben, was Sie glauben; sie prüfen es nicht. Für Daten, die eine Netzgrenze überschreiten, nehmen Sie einen Laufzeitvalidator.