JSON a TypeScript
Genera interfaces TypeScript a partir de JSON
Acerca de JSON a TypeScript
«JSON a TypeScript» lee una muestra JSON y escribe las interfaces TypeScript que la describen, con el motor quicktype-core en tu navegador. Cada objeto anidado se convierte en su propia interfaz exportada, y se examina cada elemento de un array: una clave que falta en algunos elementos recibe un signo de interrogación, y un valor que a veces es null se tipa con null en una unión. Las claves que no son identificadores válidos, como first-name, se escriben entre comillas. Solo genera tipos: ni clases, ni comprobaciones en tiempo de ejecución, ni enums, fechas o tipos UUID deducidos de valores de cadena.
Ejemplo
Dos registros de usuarios de una API: lastLogin es null en el segundo, address solo existe en el primero, tags está vacío en el segundo y manager-id no es un identificador válido. La salida de abajo es exactamente lo que escribe «Convertir».
Entrada JSON
[{"id": 101, "email": "ada@example.com", "role": "admin",
"lastLogin": "2026-10-01T08:30:00Z",
"address": {"city": "London", "zip": "N1 9GU"},
"tags": ["beta"], "manager-id": null},
{"id": 102, "email": "lin@example.com", "role": "editor",
"lastLogin": null, "tags": [], "manager-id": 101}]Salida TypeScript
export interface Root {
id: number;
email: string;
role: string;
lastLogin: null | string;
address?: Address;
tags: string[];
"manager-id": number | null;
}
export interface Address {
city: string;
zip: string;
}Cómo generar interfaces TypeScript a partir de JSON
- 1Pega un objeto JSON, o un array de varios objetos representativos, en «Entrada JSON».
- 2Haz clic en «Convertir»; el motor se carga con el primer clic y luego las interfaces llenan «Salida TypeScript».
- 3Compara las claves opcionales y las uniones con null con los datos que tu código recibirá de verdad.
- 4Haz clic en «Copiar», o en «Descargar» para guardar el código como «types.ts».
Formatos y límites
- Entrada
- Texto JSON: un objeto, o un array de objetos cuyos elementos se combinan; un array de valores simples da un mensaje en lugar de código
- Salida
- Interfaces TypeScript exportadas, una por objeto anidado, guardadas como types.ts
- Claves opcionales
- Un signo de interrogación cuando falta una clave en algunos elementos del array; null en una unión cuando un valor es null
- No se genera
- Clases, validación en tiempo de ejecución, enums, tipos de fecha o UUID (las cadenas siguen siendo string)
Usos habituales
- Tipar la respuesta de una API REST
- Quien desarrolla el front-end copia una respuesta de GET /users desde la pestaña Red del navegador, pega el array completo y obtiene una interfaz Root que describe un usuario, más una interfaz por cada objeto anidado, para tipar el resultado de la llamada a fetch.
- Describir un archivo de configuración
- Un archivo JSON de feature flags o de configuración de la aplicación se convierte en una interfaz, así que el editor autocompleta sus claves y señala una mal escrita en el código que las lee.
- Encontrar los campos que omite una fuente de datos
- Pegar 50 registros del historial de un webhook o de una exportación de datos muestra, con los signos de interrogación y las uniones con null, qué claves omiten algunos registros y cuáles son a veces null, antes de que el código dé por hecho que siempre están.
Qué herramienta elegir
- Formateador JSON: cuando «Convertir» responde con un mensaje «JSON no válido», muestra la línea con el error con un ^ debajo del problema, para que corrijas la muestra y la vuelvas a pegar aquí.
- JSON a struct de Go: el mismo motor quicktype y la misma combinación de los elementos de un array, pero el código se escribe como structs de Go con etiquetas json y campos int64 o float64 en lugar de interfaces TypeScript.
- TypeScript a JavaScript: la tarea contraria: quita las anotaciones de tipo y las interfaces del código fuente TypeScript para dejar JavaScript sin más, y no lee JSON.
Dónde se procesa tu JSON
Las interfaces se generan en tu navegador: la página obtiene el motor quicktype con tu primer clic, y tu JSON no se sube, ni tampoco el TypeScript que produce. Si aparece un mensaje de error, una copia abreviada de ese mensaje, sin el texto citado, los números largos ni las direcciones, se envía a nuestro registro de errores junto con el nombre de la herramienta y el nombre y la versión de tu navegador, para poder corregir la herramienta.
Preguntas frecuentes
¿Detecta los campos opcionales?
Sí, cuando pegas un array. Se combinan todos los elementos: una clave que falta en algunos se escribe con un signo de interrogación, y una clave que es null en algunos recibe null en su tipo, por ejemplo null | string. Con un solo objeto, todas las claves que contiene son obligatorias.
¿Cómo se tipan los objetos y los arrays anidados?
Cada objeto anidado se convierte en una interfaz exportada aparte, con el nombre de su clave, como Team para una clave team, y un array de objetos se convierte en un array de esa interfaz. Los arrays de cadenas o de números pasan a ser string[] o number[]. Un árbol que repite su propia forma, como {"name": "a", "children": [{"name": "b", "children": []}]}, da children: Root[] en lugar de una cadena interminable de interfaces.
¿Qué pasa con las claves con guiones o espacios?
Conservan su escritura exacta como nombres de propiedad entre comillas, lo que es TypeScript válido, así que la interfaz coincide con el JSON sin cambiar ningún nombre. Las claves que son identificadores válidos, como nickname, se escriben sin comillas.
¿Puedo guardar el resultado como archivo .ts?
Sí. Después de una conversión, aparece bajo la salida una fila llamada types.ts con un botón «Descargar»; en iPhone y iPad se añade a su lado un botón «Guardar o compartir». «Copiar» pone el mismo código en el portapapeles.
¿Qué tipo recibe un campo cuyos valores mezclan números y cadenas?
Una unión de todos los tipos encontrados. [{"a": 1}, {"a": "x"}] da a: number | string, y un array que contiene 1, "a" y true se tipa Array<boolean | number | string>.
¿En qué se convierte un array vacío?
En unknown[], porque la muestra no dice nada de sus elementos. Pega registros en los que ese array tenga al menos un elemento, y el tipo combinado pasa a ser string[], number[] o un array de interfaces.
¿Puedo elegir el nombre de la raíz u obtener alias de tipo en lugar de interfaces?
No. La interfaz de primer nivel siempre se llama Root y cada forma se escribe como una interfaz exportada. Cambia el nombre de Root en tu editor, y cambia tú mismo interface por type si tu código prefiere los alias.
¿Y si dos objetos anidados comparten el nombre de una clave, pero no los mismos campos?
Cada forma recibe su propia interfaz, con el nombre de su padre delante: un address dentro de user y otro dentro de company pasan a ser UserAddress y CompanyAddress, así que ninguno sobrescribe al otro.
¿Es seguro tipar como number los ID numéricos largos?
No siempre. JavaScript solo guarda con exactitud los números enteros hasta 9 007 199 254 740 991, y aquí cada número JSON se tipa number. Cuando el JSON contiene un número entero mayor, un comentario al principio de la salida indica cuántos hay: JSON.parse los redondea, así que conserva esos ID como cadenas en la API o léelos como bigint.
¿Por qué dos claves distintas comparten una interfaz con un nombre raro?
Los objetos con exactamente los mismos campos y tipos se combinan en una sola interfaz, con un nombre sacado de las claves que los contienen. {"home": {"city": "x", "zip": "1"}, "work": {"city": "y", "zip": "2"}} da home: Home y work: Home; billing y shipping con los mismos campos comparten una interfaz llamada Ing, la terminación que tienen en común los dos nombres. La forma es correcta: cambia el nombre de la interfaz en tu editor.
¿Cuándo se convierte un objeto en { [key: string]: T } en lugar de una interfaz?
Cuando sus claves parecen datos y no nombres de campo, y todos sus valores tienen un mismo tipo. {"byId": {"1": {...}, "2": {...}}} da byId: { [key: string]: ByID }, y unos tipos de cambio con las claves USD, EUR, GBP y JPY dan { [key: string]: number }. Con solo USD, EUR y GBP, o con claves que son palabras como red, green y blue, cada clave sigue siendo un campo con nombre. Es una heurística del motor, así que revisa los objetos cuyas claves son ID o códigos.
¿Por qué un array de cadenas o de números no da ninguna interfaz?
Un array de primer nivel con valores simples, como ["a", "b"], [1, 2, 3], [] o [[1]], no tiene ningún objeto que describir, así que el motor no escribe código y la página muestra un mensaje en su lugar. Pon el array dentro de un objeto: {"items": ["a", "b"]} da items: string[].
¿Por qué una fecha ISO se tipa como string y no como Date?
Porque JSON.parse devuelve "2026-10-01T08:30:00Z" como cadena, no como Date. Una interfaz que dijera Date permitiría que el código llamara a getTime() sobre un valor que sigue siendo texto en tiempo de ejecución. Lo mismo pasa con los UUID y con los números escritos entre comillas, como "42": siguen tipados como string hasta que tu código los convierte.
¿Comprueba que los datos coinciden de verdad con las interfaces?
No. Las interfaces de TypeScript se borran al compilar el código, así que describen los datos que esperas sin comprobar lo que llega. La salida no contiene código de validación ni esquema de Zod; úsala como la forma que debes seguir cuando escribas uno.
Consejos y trucos
- ✓Cambia el nombre de la interfaz Root después de pegarla en tu proyecto; el nombre viene de la herramienta, no de tus datos.
- ✓Si el resultado es un mensaje «JSON no válido», abre el mismo texto en «Formateador JSON», que indica la línea y la columna del error.