Generar tipos TypeScript a partir de un Schema
En resumen: json-schema-to-typescript y quicktype emiten un .d.ts con un solo comando, pero es un borrador: la opcionalidad, las uniones, additionalProperties y las fechas necesitan una pasada humana.

En resumen: genera con json-schema-to-typescript o quicktype, y luego corrige a mano la opcionalidad, las uniones, additionalProperties y las fechas; mantén el Schema como origen y los tipos como salida, impuesto por un paso types:check en CI.
Un comando te da un archivo. No te da tipos correctos.
El comando de una línea
npx json-schema-to-typescript schema.json > src/types/order.d.ts
Maneja $ref, allOf, oneOf, anyOf, y convierte description en JSDoc. Para generación por lotes con una cabecera y un style elegido, llama a su API de Node desde un pequeño build-types.mjs.
quicktype es la alternativa, y también puede inferir un schema a partir de JSON de ejemplo:
npx quicktype -s schema schema.json -o order.ts --lang typescript
Cuatro cosas que corregir después
Opcionalidad. Cualquier cosa que no esté en required se convierte en ?. Pero «siempre presente, puede ser null» y «puede estar ausente» son contratos distintos:
interface Order {
remark?: string | null; // may be missing
status: string;
}
Si el backend siempre envía remark: null, quita el ? y deja de hacer que cada consumidor se proteja contra undefined.
Uniones sin discriminante. oneOf normalmente se convierte en A | B, que TypeScript no puede estrechar sin un campo literal. Añade una propiedad type fija a cada rama en el Schema.
additionalProperties. Omitido o true a veces produce [k: string]: unknown, a veces any. El primero es seguro; el segundo desactiva en silencio la comprobación de tipos para todo el objeto.
Formatos de fecha. format: "date-time" es una cadena en el cable. Mapearlo a Date significa que también debes deserializar, o el valor en tiempo de ejecución sigue siendo una cadena mientras el tipo miente.
Mantén fija la dirección
El Schema es el origen, los tipos son la salida. Generar el Schema a partir de tipos escritos a mano solo es aceptable si la regeneración es obligatoria y se impone en CI; de lo contrario, ambos lados se desvían y nadie sabe cuál es la fuente de verdad.
Intégralo en el pipeline
"types:gen": "json2ts -i schemas/ -o src/types/generated",
"types:check": "pnpm types:gen && git diff --exit-code src/types/generated"
types:check es la parte que importa: cambia el Schema sin regenerar y CI falla.
FAQ
¿Por qué el archivo generado contiene any?
Normalmente viene de que additionalProperties es true o está omitido, y algunos generadores lo mapean a [k: string]: any. Sustitúyelo por unknown o por campos explícitos, porque any desactiva la comprobación de tipos para todo el objeto.
¿Cómo debería corregir los campos opcionales después de generar?
Cualquier cosa fuera de required se convierte en ?, pero «siempre presente, puede ser null» difiere de «puede estar ausente». Si el backend siempre envía el campo, quita el ?.
¿Debería fallar CI cuando el Schema y los tipos se desvían?
Sí. Un script types:check que regenera y ejecuta git diff --exit-code hace fallar la compilación en cuanto el Schema cambia sin regenerarse.