Cómo funciona la inferencia JSON a TypeScript
La inferencia es un único recorrido sobre el árbol JSON analizado. La herramienta lee cada valor, elige un tipo TypeScript para él y luego escribe una interfaz por cada objeto encontrado.
- Analiza la muestra JSON con el analizador nativo del navegador y rechaza la entrada malformada con una pista de línea/columna.
- Detecta un tipo TypeScript para cada valor —
string,number,boolean,null, array u objeto anidado. - Asigna a cada objeto anidado un nombre de interfaz derivado de la clave de la propiedad padre (para que
user.addressse convierta en una interfazAddress). - Fusiona los tipos de elementos en cada array para que una lista de
{id: 1}y{id: 2, label: "x"}produzca una unión con los campos opcionales correctos. - Aplica tus opciones (interface vs. type, readonly, opcional-anulable) y emite las declaraciones en orden de dependencia para que el archivo compile sin referencias adelantadas.
¿Por qué generar tipos TypeScript desde JSON?
- La mayoría de los errores de forma son detectables en tiempo de compilación si el tipo de respuesta está escrito. Inferir una interfaz desde una carga útil real escribe la mayor parte por ti, y el modo `strict` detecta el campo que la documentación olvidó mencionar.
- Combinar interfaces inferidas con un validador en tiempo de ejecución como Zod o io-ts le da a la misma forma dos trabajos: autocompletado en el editor durante el desarrollo y un error 400 en el borde cuando producción envía algo inesperado.
- El servidor de lenguaje de TypeScript solo muestra los campos que conoce. Una vez que importas la interfaz inferida, el autocompletado funciona en el momento en que escribes el punto — sin más casts `as any` en la respuesta y una búsqueda frustrada en el repositorio.
- Si estás a punto de escribir una especificación OpenAPI, una interfaz inferida es un primer borrador rápido del esquema de respuesta. Todavía querrás ejemplos y restricciones escritos a mano, pero los nombres de las propiedades y los tipos ya son correctos.
Aplicaciones comunes
La inferencia ayuda más cuando existe una carga útil real pero no hay un esquema.
- Tipar cargas útiles de webhooks de terceros de Stripe, GitHub o Twilio antes de escribir un controlador.
- Arrancar tipos para una API REST interna para que el equipo de frontend pueda empezar a programar contra ella el mismo día que llega el backend.
- Generar un punto de partida para un esquema Zod, io-ts o Valibot desde una respuesta de API observada.
¿Cómo es la salida?
Dado un documento JSON de muestra y un nombre raíz, el generador produce un árbol de interfaces, una por cada objeto anidado. Para la entrada de abajo con nombre raíz User:
Pega {"id":1,"name":"Alice","tags":["a","b"],"address":{"city":"Paris"}} con nombre raíz User y el generador produce:
export interface User {
id: number;
name: string;
tags: string[];
address: Address;
}
export interface Address {
city: string;
}
Observa que address fue promovido a su propia interfaz nombrada — esa es la salida ordenada por dependencias. El mismo JSON con el estilo de declaración type emitiría export type User = {...}; con el toggle readonly activado, cada propiedad obtiene el modificador readonly.
Opciones del generador
Estilo de declaración
Elige interface (el idioma TypeScript estándar para formas de objetos) o type (útil si necesitarás tipos mapeados, tipos condicionales o intersecciones más adelante). Ambos producen un comportamiento en tiempo de ejecución idéntico; la elección es una preferencia de estilo de código.
Campos opcionales anulables
Cuando un valor muestreado es null, el tipo del campo se convierte en T | null. Activar esta opción también añade un modificador ? para que el campo sea opcional en el lado TypeScript — útil cuando la API a veces omite la clave por completo en lugar de devolver null.
Modificador Readonly
Antepone readonly a cada declaración de propiedad para que la interfaz emitida coincida con un modelo de datos inmutable. Útil para slices de estado de Redux, respuestas de API congeladas o en cualquier lugar donde quieras que el compilador señale mutaciones accidentales.
¿Admite objetos anidados y arrays?
Sí. Cada objeto anidado se convierte en una interfaz nombrada derivada de la clave de la propiedad padre, y los arrays infieren el tipo de elemento de su contenido. Los arrays de objetos obtienen una interfaz por forma de objeto, con tipos unión donde las formas no coinciden.
¿Cómo se infieren los campos opcionales?
Activa el toggle "Marcar campos anulables como opcionales" y cualquier campo cuyo valor muestreado sea null obtiene un modificador ? en la clave más | null en el tipo. Sin el toggle, el campo sigue siendo requerido y el tipo es simplemente T | null.
¿Admite uniones discriminadas?
Los tipos unión básicos salen cuando un array contiene elementos de forma mixta o cuando un campo lleva tanto un valor como null. La inferencia de unión discriminada completa (elegir type o kind como etiqueta y dividir las variantes) necesita múltiples muestras — eso está planificado pero no está en la compilación actual.
¿Puedo inferir tipos desde múltiples muestras JSON?
Todavía no — el inferidor actual lee una muestra a la vez. Si tienes dos cargas útiles que deberían compartir una interfaz (por ejemplo, un endpoint de lista y un endpoint de elemento único), la solución práctica es fusionarlas en un array, generar desde eso y luego renombrar los tipos unión resultantes. La inferencia de múltiples muestras está en el roadmap porque es la única forma de detectar campos que están presentes en una respuesta y ausentes en otra.
Pega una carga útil, nombra la raíz, copia las interfaces. Todo el pipeline se ejecuta en tu navegador, por lo que una API no publicada o un cuerpo de webhook firmado permanece en tu máquina.