TypeScript-Typen aus einem Schema generieren
Fazit: json-schema-to-typescript und quicktype erzeugen mit einem Befehl eine .d.ts, aber das ist ein Entwurf: Optionalität, Unions, additionalProperties und Daten brauchen einen menschlichen Durchgang.

Kurz gesagt: Generieren Sie mit json-schema-to-typescript oder quicktype und korrigieren Sie dann Optionalität, Unions, additionalProperties und Daten von Hand; behalten Sie Schema als Quelle und Typen als Ausgabe, erzwungen durch einen types:check-Schritt in CI.
Ein Befehl liefert Ihnen eine Datei. Er liefert Ihnen keine korrekten Typen.
Der Einzeiler
npx json-schema-to-typescript schema.json > src/types/order.d.ts
Es behandelt $ref, allOf, oneOf, anyOf und wandelt description in JSDoc um. Für die Batch-Generierung mit Banner und gewähltem style rufen Sie seine Node-API aus einem kleinen build-types.mjs auf.
quicktype ist die Alternative und kann auch ein Schema aus Beispiel-JSON inferieren:
npx quicktype -s schema schema.json -o order.ts --lang typescript
Vier Dinge, die danach zu korrigieren sind
Optionalität. Alles, was nicht in required steht, wird zu ?. Aber „immer vorhanden, darf null sein“ und „kann fehlen“ sind verschiedene Verträge:
interface Order {
remark?: string | null; // may be missing
status: string;
}
Sendet das Backend immer remark: null, entfernen Sie das ? und hören Sie auf, jeden Konsumenten gegen undefined absichern zu lassen.
Undiskriminierte Unions. oneOf wird meist zu A | B, was TypeScript ohne ein Literalfeld nicht einschränken kann. Ergänzen Sie im Schema in jedem Zweig eine feste type-Eigenschaft.
additionalProperties. Weggelassen oder true ergibt manchmal [k: string]: unknown, manchmal any. Ersteres ist sicher, Letzteres deaktiviert stillschweigend die Typprüfung für das ganze Objekt.
Datumsformate. format: "date-time" ist auf der Leitung ein String. Es auf Date abzubilden bedeutet, Sie müssen auch deserialisieren, sonst bleibt der Laufzeitwert ein String, während der Typ lügt.
Die Richtung festhalten
Schema ist die Quelle, Typen sind Ausgabe. Das Schema aus handgeschriebenen Typen zu generieren ist nur akzeptabel, wenn die Neugenerierung verpflichtend und in CI erzwungen ist – sonst driften beide Seiten und niemand weiß, welche maßgeblich ist.
In die Pipeline einbinden
"types:gen": "json2ts -i schemas/ -o src/types/generated",
"types:check": "pnpm types:gen && git diff --exit-code src/types/generated"
types:check ist der entscheidende Teil: Ändern Sie das Schema ohne Neugenerierung, und CI scheitert.
FAQ
Warum enthält die generierte Datei any?
Es kommt meist daher, dass additionalProperties true ist oder weggelassen wurde, was manche Generatoren auf [k: string]: any abbilden. Ersetzen Sie es durch unknown oder ausdrückliche Felder, weil any die Typprüfung für das ganze Objekt deaktiviert.
Wie sollte ich optionale Felder nach der Generierung korrigieren?
Alles außerhalb von required wird zu ?, aber „immer vorhanden, darf null sein“ unterscheidet sich von „kann fehlen“. Sendet das Backend das Feld immer, entfernen Sie das ?.
Sollte CI scheitern, wenn Schema und Typen driften?
Ja. Ein types:check-Skript, das neu generiert und git diff --exit-code ausführt, lässt den Build scheitern, sobald sich das Schema ohne Neugenerierung ändert.