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 silenciosamente la seguridad de tipos en lugar de lanzar un error de compilación. Generar la interfaz directamente 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 en realidad son IDs frente a cantidades: JSON tiene un único tipo number, pero 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 simplemente emiten number y te dejan la distinción a ti.
Arrays vacíos: un array sin ejemplos dentro ("tags": []) no le da al generador nada de lo que inferir el tipo de elemento — normalmente recurre a unknown[] o any[]. Apunta el generador a una muestra donde el array esté poblado, o anótalo manualmente después.
Uniones de literales de cadena: un campo status que siempre es uno de "pending" | "active" | "closed" se inferirá como simple string salvo que el generador vea todos los valores posibles en la muestra — e incluso entonces, la mayoría de generadores usan por defecto el tipo más amplio string salvo que actives explícitamente la inferencia de unions literales.
Fechas: JSON no tiene tipo de fecha — los timestamps siempre son cadenas (ISO 8601) o números (epoch de Unix). Un generador tipará un campo de fecha como string o number, no como Date; todavía tienes que analizarlo tú mismo 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 sin importar el 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 opcional Optional[...]; 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, generar los tipos para cada uno desde la misma muestra JSON los mantiene honestos entre sí.
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
Los tipos generados son un punto de partida sólido, no un contrato final. Antes de hacer commit: confirma los campos opcionales contra la documentación real de la API (no solo una muestra), sustituye los campos string sueltos que en realidad son enums por unions literales, comprueba que los campos de array vacío hayan recibido 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 se le dan — debería inferir string | number. Con una sola muestra, solo puede tipar lo que vio. Esta es la razón principal para generar a partir de múltiples cargas útiles representativas en lugar de un único ejemplo del camino feliz.
- ¿Deberían las interfaces generadas usar `interface` o `type`?
- Funcionalmente casi idénticas para este caso de uso. `interface` es más común para formas de objeto y admite declaration merging; `type` es más flexible para unions e intersecciones. Ambas sirven para formas de respuesta de API — elige la que coincida con la convención existente 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 verdaderamente recursivas (un comentario que puede contener respuestas de la misma forma) necesitan un tipo autorreferencial, que la mayoría de generadores no inferirá automáticamente de una sola muestra — típicamente tendrás que escribir a mano la interfaz recursiva una vez y reutilizarla.
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.