Generar tipos TypeScript a partir de JSON: una guía práctica
Escribir a mano una interfaz de TypeScript para una respuesta de API de 40 campos es tedioso y propenso a errores. Un typo en un nombre de campo rompe la seguridad de tipos sin ningún error de compilación. Generar la interfaz a partir de una muestra real de JSON es más rápido y preciso, siempre que entiendas dónde la inferencia tiene que adivinar.
Cómo funciona la inferencia de JSON a TypeScript
Un generador recorre el árbol de valores JSON y mapea cada tipo de JavaScript a su equivalente de TypeScript: string sigue siendo string, number sigue siendo number, boolean sigue siendo boolean, null se convierte en null (o se fusiona en una unión), los arrays se convierten en T[] donde T se infiere de los elementos, y los objetos se convierten en interfaces anidadas.
{
"id": 42,
"email": "ada@example.com",
"isActive": true,
"roles": ["admin", "editor"],
"profile": {
"displayName": "Ada",
"avatarUrl": null
}
}interface Root {
id: number;
email: string;
isActive: boolean;
roles: string[];
profile: {
displayName: string;
avatarUrl: string | null;
};
}Dónde la inferencia tiene que adivinar
Campos opcionales frente a siempre presentes: una sola muestra JSON no puede decirle a un generador si avatarUrl a veces falta por completo (lo que debería ser avatarUrl?: string | null) o siempre está presente pero a veces es null. Dale al generador unas cuantas muestras representativas, o marca manualmente un campo como opcional tras la generación si sabes que la API lo omite bajo ciertas condiciones.
Números que guardan IDs frente a cantidades: JSON tiene un único tipo number, y TypeScript no puede distinguir un ID entero de un precio de coma flotante sin contexto extra. Algunos generadores ofrecen tipos con marca o unions literales para esto; la mayoría emite number y te deja la distinción a ti.
Arrays vacíos: un array sin elementos ("tags": []) no le da al generador nada para inferir el tipo de elemento, así que recurre a unknown[] o any[]. Apunta el generador a una muestra donde el array tenga elementos, o anótalo a mano después.
Uniones de literales de cadena: el generador inferirá como string simple un campo status que contiene uno de "pending" | "active" | "closed", salvo que vea todos los valores posibles en la muestra. Incluso entonces, la mayoría de generadores usa por defecto el tipo string más amplio salvo que actives la inferencia de unions literales.
Fechas: JSON no tiene tipo de fecha, así que los timestamps llegan como cadenas (ISO 8601) o números (epoch de Unix). Un generador tipa un campo de fecha como string o number, no como Date, y tú lo sigues analizando tras el fetch.
La misma idea en otros lenguajes
La lógica de inferencia (recorrer el árbol, mapear tipos, nombrar objetos anidados) es la misma para cualquier lenguaje destino; solo cambia la sintaxis de salida. Un struct de Go recibe el mismo mapeo de campos con etiquetas de struct para los nombres de clave JSON; un dataclass de Python recibe type hints y un envoltorio Optional[...] donde haga falta; una clase de Java o C# recibe campos tipados y getters/setters o records. Si tu equipo trabaja en varios lenguajes contra la misma API, genera los tipos de cada uno desde la misma muestra JSON para que sigan siendo coherentes.
type Root struct {
ID int `json:"id"`
Email string `json:"email"`
IsActive bool `json:"isActive"`
Roles []string `json:"roles"`
Profile struct {
DisplayName string `json:"displayName"`
AvatarURL *string `json:"avatarUrl"`
} `json:"profile"`
}Antes de confiar en los tipos generados
Trata los tipos generados como punto de partida y termina tú el contrato. Antes de hacer commit, confirma los campos opcionales con la documentación de la API (una muestra no basta), sustituye por unions literales los campos string sueltos que guardan enums, comprueba que los campos de array vacío recibieron un tipo de elemento real a partir de una muestra mejor, y regenera cada vez que la API aguas arriba añada o renombre un campo en lugar de parchear la interfaz a mano.
FAQ
- ¿Puede un generador JSON a TypeScript manejar un campo que a veces es string y a veces number?
- Sí, si ve ambas variantes entre las muestras que le das; debería inferir string | number. Con una sola muestra, solo puede tipar lo que vio. Por eso conviene generar a partir de varias cargas útiles representativas y no de un único ejemplo del camino feliz.
- ¿Deberían las interfaces generadas usar `interface` o `type`?
- Para este caso funcionan casi igual. `interface` es más común para formas de objeto y admite declaration merging; `type` maneja mejor unions e intersecciones. Ambas sirven para formas de respuesta de API, así que sigue la convención de tu base de código.
- ¿Cómo mantengo los tipos generados sincronizados a medida que la API evoluciona?
- Trata la generación como un paso repetible, no un copiar-pegar único: mantén una muestra real de respuesta en el repositorio (o recogiéndola de un endpoint de staging) y regenera la interfencia cada vez que cambie la muestra, en lugar de editar a mano el archivo generado. Algunos equipos lo integran en CI para detectar el desvío automáticamente.
- ¿Funciona para JSON profundamente anidado o recursivo, como una estructura de árbol?
- El anidamiento profundo genera interfaces anidadas sin problema. Las estructuras recursivas (un comentario que contiene respuestas de la misma forma) necesitan un tipo autorreferencial, y la mayoría de generadores no lo inferirá de una sola muestra. Escribe la interfaz recursiva a mano una vez y reutilízala.
Prueba estas herramientas
JSON to TypeScript →
Generate TypeScript interfaces from JSON with optional readonly modifiers and JSDoc comments.
JSON to Go →
Generate Go structs with json tags from a JSON sample, ready for encoding/json.
JSON to Python →
Generate Python TypedDict classes from a JSON sample for mypy, Pyright, and editor autocompletion.
Artículos relacionados
¿Qué es JSON? Una guía completa para principiantes →
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos, fácil de leer para los humanos y de analizar para las máquinas. Aprende la sintaxis, los tipos de datos y la estructura que impulsan las APIs modernas.
La historia de JSON: del 2000 al estándar de la industria →
Recorre JSON desde la idea de Douglas Crockford en 2001, pasando por su adopción por Yahoo, hasta convertirse en el estándar ECMA-404 que impulsa el 90 % de las APIs modernas.
La guía completa de JSON Schema (Draft 7) →
JSON Schema es el estándar para describir y validar la estructura de JSON. Aprende las palabras clave principales, crea un esquema de API real y aplica buenas prácticas.