Generar tipos TypeScript desde JSON — la forma correcta
Generar tipos a partir de una respuesta de ejemplo tarda segundos. Conseguir tipos en los que puedas confiar requiere algunas decisiones más: qué es opcional, qué puede ser nulo, cómo nombrar las cosas y cómo asegurarte de que la API cumple su palabra en tiempo de ejecución.
Empieza con respuestas reales
Pega una respuesta en el conversor de JSON a TypeScript y obtendrás interfaces para cada objeto anidado. Sin embargo, un solo ejemplo muestra una única forma, así que pega un array de varios objetos reales: el conversor los combina y marca como opcionales los campos que faltan en algunos de ellos.
[
{ "id": 1, "name": "Ada", "email": "ada@example.com", "team": { "id": 7, "name": "Core" } },
{ "id": 2, "name": "Grace", "email": null }
]
interface User {
id: number;
name: string;
email: string | null;
team?: Team;
}
interface Team {
id: number;
name: string;
}
Opcional no es lo mismo que nullable
team?: Team significa que la clave puede estar ausente. email: string | null significa que la clave siempre está presente, aunque puede valer null. Las APIs las usan de forma distinta y tu código las comprueba de forma distinta ('team' in user frente a user.email === null), así que mantén la diferencia en lugar de convertirlo todo en ?: … | null.
Ajusta lo que la muestra no puede revelar
- Uniones literales: un campo
statusque aparece como"active"se convierte enstring; sustitúyelo por'active' | 'paused' | 'deleted'según la documentación de la API. - Las fechas llegan como cadenas ISO. Tipalas como
stringy conviértelas en el punto de entrada; no finjas que son objetosDate. - Los IDs: los IDs numéricos grandes (por encima de 253) pierden precisión en JavaScript; por eso muchas APIs los envían como cadenas.
- Los arrays vacíos se convierten en
unknown[]oany[]; define tú el tipo de los elementos.
Los tipos desaparecen en tiempo de ejecución
TypeScript revisa tu código, no los datos. Si la API cambia, el compilador no se dará cuenta. Valida las respuestas en el límite de tu aplicación:
- Genera un esquema a partir de las mismas muestras con JSON a JSON Schema.
- Edítalo (campos obligatorios, enums, formatos como
date-time) y prueba cargas reales en el validador de JSON Schema. - Valida en tu app con una librería como Ajv y genera los tipos desde el esquema (JSON Schema a TypeScript) para tener una única fuente de verdad.
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(userSchema);
const data = await res.json();
if (!validate(data)) throw new Error('Unexpected API response: ' + ajv.errorsText(validate.errors));
Librerías como Zod o Valibot hacen lo mismo con el esquema escrito en el propio TypeScript, y deducen el tipo a partir de él.
Nombres y estructura
Dale al tipo raíz un nombre significativo (User, no Root), exporta los tipos desde un único módulo y prefiere interface para las formas de objeto que puedas extender. Antes de nada, formatea e inspecciona las respuestas grandes con el formateador de JSON para ver qué ramas importan.