JSON Toolkit

Generowanie typów TypeScript ze schematu

Podsumowanie: json-schema-to-typescript i quicktype generują .d.ts jedną komendą, ale to szkic: opcjonalność, unie, additionalProperties i daty wymagają ręcznego przejścia.

Średniozaawansowany~4 min czytaniaOpublikowano 2026-10-30Zaktualizowano 2026-10-30
Generowanie typów TypeScript z JSON Schema

Najważniejsze: generuj przez json-schema-to-typescript lub quicktype, a potem ręcznie popraw opcjonalność, unie, additionalProperties i daty; trzymaj Schema jako źródło i typy jako wynik, wymuszone etapem types:check w CI.

Jedna komenda daje plik. Nie daje poprawnych typów.

Jednolinijkowiec

npx json-schema-to-typescript schema.json > src/types/order.d.ts

Radzi sobie z $ref, allOf, oneOf, anyOf i zamienia description w JSDoc. Do generowania wsadowego z bannerem i wybranym style wywołaj jego Node API z małego build-types.mjs.

quicktype jest alternatywą i potrafi też wnioskować schemat z przykładowego JSON:

npx quicktype -s schema schema.json -o order.ts --lang typescript

Cztery rzeczy do poprawienia po fakcie

Opcjonalność. Cokolwiek poza required, staje się ?. Ale „zawsze obecne, może być null” i „może być nieobecne” to różne kontrakty:

interface Order {
  remark?: string | null;   // may be missing
  status: string;
}

Jeśli backend zawsze wysyła remark: null, usuń ? i przestań kazać każdemu konsumentowi chronić się przed undefined.

Unie bez dyskryminatora. oneOf zwykle staje się A | B, którego TypeScript nie potrafi zawęzić bez pola literałowego. Dodaj stałą właściwość type do każdej gałęzi w Schema.

additionalProperties. Pominięte lub true czasami daje [k: string]: unknown, a czasami any. Pierwsze jest bezpieczne, drugie po cichu wyłącza sprawdzanie typów dla całego obiektu.

Formaty daty. format: "date-time" to łańcuch na łączu. Mapowanie go na Date oznacza, że musisz też deserializować, inaczej wartość w czasie wykonania pozostaje łańcuchem, a typ kłamie.

Utrzymaj stały kierunek

Schema jest źródłem, typy są wynikiem. Generowanie Schema z ręcznie pisanych typów jest akceptowalne tylko wtedy, gdy regeneracja jest obowiązkowa i wymuszana w CI — inaczej obie strony dryfują i nikt nie wie, która jest autorytatywna.

Umieść to w potoku

"types:gen": "json2ts -i schemas/ -o src/types/generated",
"types:check": "pnpm types:gen && git diff --exit-code src/types/generated"

types:check to część, która ma znaczenie: zmień Schema bez regeneracji, a CI zawodzi.

FAQ

Dlaczego wygenerowany plik zawiera any?

Zwykle pochodzi z additionalProperties ustawionego na true lub pominiętego, które niektóre generatory mapują na [k: string]: any. Zastąp to unknown lub jawnymi polami, bo any wyłącza sprawdzanie typów dla całego obiektu.

Jak poprawić pola opcjonalne po generowaniu?

Cokolwiek poza required, staje się ?, ale „zawsze obecne, może być null” różni się od „może być nieobecne”. Jeśli backend zawsze wysyła pole, usuń ?.

Czy CI powinno zawodzić, gdy Schema i typy dryfują?

Tak. Skrypt types:check, który regeneruje i uruchamia git diff --exit-code, psuje budowanie, gdy tylko Schema zmieni się bez regeneracji.

Dodatkowe materiały