JSON a TypeScript
Convierte automáticamente datos JSON a interfaces o definiciones de tipo TypeScript
// Las definiciones de tipo TypeScript se generarán automáticamente¿Qué es JSON a TypeScript?
JSON to TypeScript analiza una estructura JSON y genera interfaces o alias de tipo de TypeScript a partir de ella. Es útil cuando respuestas de API, archivos de configuración, payloads de ejemplo o datos simulados deben entrar rápidamente en un proyecto frontend o Node.js tipado. La herramienta infiere objetos, arrays, propiedades anidadas, campos opcionales y tipos básicos, convirtiendo datos sin formato en una base práctica para autocompletado y comprobaciones en compilación. Aun así, requiere revisión: un ejemplo JSON puede no cubrir todos los campos, los arrays vacíos no muestran la forma de sus elementos y una API real puede devolver null o variantes.
Cómo usar
Cómo usar
- Pega datos JSON en el panel izquierdo, o haz clic en el botón de ejemplo para cargar uno
- Configura las opciones: define el nombre del tipo raíz, elige el estilo de interfaz/tipo y si quieres añadir export
- Las definiciones de tipo TypeScript correspondientes se generan automáticamente a la derecha
- Haz clic en el botón Copy para copiar las definiciones de tipo generadas al portapapeles
- Pega las definiciones de tipo en tu proyecto TypeScript para usarlas
Consejos de generación de tipos
- Usa muestras de JSON representativas. Un solo ejemplo no puede revelar cada campo opcional, valor nullable o tipo unión en una API real.
- Revisa los nombres generados antes de confirmarlos, especialmente para objetos anidados donde los nombres de interfaz automáticos pueden ser demasiado genéricos.
Casos de uso
Principio técnico
JSON a TypeScript es fundamentalmente un proceso de 'inferencia de estructura'. La herramienta recorre recursivamente cada nodo del árbol JSON, mapeando el tipo en tiempo de ejecución de cada valor a un tipo TypeScript: string -> string, number -> number, boolean -> boolean, null -> null, object -> sub-interfaz, array -> array del tipo del elemento. La salida es un conjunto de declaraciones `interface` de TypeScript (o alias `type` si se selecciona el modo de salida 'type') más las interfaces anidadas extraídas de campos con valores de objeto. La parte difícil de la inferencia es la decisión entre unión y tipo único para arrays. Cuando todos los elementos de un array tienen el mismo tipo, la salida es `T[]` (array homogéneo). Cuando los elementos tienen tipos diferentes, la salida es la unión de esos tipos: `[1, 'a', true]` se convierte en `(number | string | boolean)[]`. Cuando la entrada es un objeto que mezcla valores literales y estructurados (p. ej. `{ id: 1, name: 'Alice', tags: ['admin', 'editor'] }`), cada campo obtiene su propio tipo; para objetos con valores primitivos mixtos la página emite una sola interfaz, no una unión, porque es lo que el código TypeScript espera (y coincide con la naturaleza del objeto JSON como tipo registro). Los múltiples objetos de muestra (el caso de uso típico: pegar un array JSON) se fusionan intersecando sus formas. Los campos presentes en cada muestra se vuelven obligatorios; los campos que faltan en alguna muestra se vuelven opcionales (`fieldName?: T`). Este es el comportamiento correcto para respuestas de API: una respuesta 200 OK tiene una forma, una 404 tiene otra, y la unión de ambas es el tipo TS correcto. Para una sola muestra, todos los campos son obligatorios. La normalización de nombres es donde la mayoría de las herramientas de 'JSON a TS' fallan. Las claves JSON suelen estar en snake_case (`user_id`, `created_at`) o camelCase (`userId`, `createdAt`); la convención de TypeScript es PascalCase para nombres de interfaz (`UserProfile`, `AuditEntry`) y camelCase para nombres de propiedad. La página convierte las claves JSON a camelCase (o las preserva si ya están en camelCase o son una sola palabra) y PascalCase para nombres de interfaz. Los objetos internos se extraen en interfaces con nombre: `{ user: { name, age } }` se convierte en `interface User { name: string; age: number; }` y el padre se convierte en `interface Root { user: User; }`. Las estructuras recursivas (un nodo de árbol con un campo `children: TreeNode[]`) obtienen una autorreferencia usando una declaración `type` adelantada en lugar de `interface` para que el ciclo esté bien definido. El interruptor 'root' es la diferencia entre un array raíz y un objeto raíz. Un array JSON se convierte en `type Root = Item[]` o `interface Root { items: Item[]; ... }` dependiendo del interruptor de envoltura de array. Un objeto JSON se convierte en una interfaz plana en el nivel superior. Las cadenas de fecha (RFC 3339 / ISO 8601) pueden etiquetarse como `Date` en lugar de `string`; los UUID, emails y URLs pueden etiquetarse como tipos con marca (`type UUID = string & { readonly __brand: 'UUID' };`) cuando el interruptor de modo estricto está activado. La generación de JSDoc es heurística: un campo llamado `email` (y cuyo valor coincide con un regex básico de email) recibe un comentario como `/** user email */` encima de la declaración. Lo mismo para `id`, `name`, `url`, `created_at`/`createdAt`, `updated_at`/`updatedAt`, `description`, `title`. Los comentarios son de mejor esfuerzo y no pretenden ser escritos por humanos; son un punto de partida que los humanos editarán. La página también emite modificadores `export` para que la salida pueda insertarse directamente en cualquier archivo TS, y un encabezado `// generated by json-to-typescript, do not edit by hand` para desalentar ediciones manuales que se sobrescribirían la próxima vez que el esquema se regenere.
- Mapeo de tipos atómicos: los string/number/boolean/null de JSON se mapean uno a uno a los string/number/boolean/null de TypeScript. Los enteros grandes (>2^53) necesitan BigInt; la página los etiqueta como `bigint` cuando el valor excede Number.MAX_SAFE_INTEGER.
- Inferencia de tipo de array: recorre todos los elementos y toma la unión de sus tipos; los tipos idénticos colapsan a `T[]`, los tipos distintos forman `(A | B | C)[]`. Los arrays vacíos se convierten en `unknown[]` ya que el tipo del elemento es desconocido.
- Extracción de objetos anidados: los objetos internos se elevan automáticamente a interfaces con nombre. Las estructuras recursivas usan `type Name = ...` (no `interface`) para que la referencia adelantada esté bien definida en el verificador de tipos de TypeScript.
- Detección de campos opcionales: cuando se fusionan múltiples objetos de muestra, los campos presentes en cada muestra se vuelven obligatorios; los campos que faltan en alguna muestra se vuelven opcionales (`fieldName?: T`). La entrada con una sola muestra marca todos los campos como obligatorios.
- Convención de nombres: las claves JSON se convierten a camelCase para nombres de propiedad (user_id -> userId, created_at -> createdAt) y PascalCase para nombres de interfaz (UserProfile, AuditEntry). Las claves de una sola palabra se preservan; los números en claves se preservan; los dígitos iniciales se prefijan con guion bajo para mantener identificadores TS válidos.
- Interruptor raíz: array raíz -> `export type Root = Item[]` (o envuelto en `{ items: Item[]; }` si wrap-array está activado); objeto raíz -> un solo `export interface Root { ... }`. Las estructuras recursivas obtienen primero una declaración adelantada stub.
- Comentarios JSDoc: generación heurística de comentarios para nombres de campo conocidos (email, id, name, url, createdAt, updatedAt, description, title). La salida incluye modificadores `export` y un encabezado `// generated, do not edit by hand` para desalentar ediciones manuales.
- Modo estricto: activación opcional de tipos con marca (UUID, Email, URL, Date), modificadores readonly, exactOptionalPropertyTypes y noUncheckedIndexedAccess. La página emite `type UUID = string & { readonly __brand: 'UUID' };` cuando el modo estricto está activado, para que el código descendente pueda distinguir una cadena sin tipo de un valor tipado.
Ejemplos
Objeto simple a interface
{"id": 1, "name": "Alice", "active": true}
->
interface User {
id: number;
name: string;
active: boolean;
}Objeto anidado genera sub-interfaces
{"user": {"name": "Alice", "address": {"city": "NYC"}}}
->
interface Root {
user: User;
}
interface User {
name: string;
address: Address;
}
interface Address {
city: string;
}Array a tupla readonly
[{"id": 1}, {"id": 2}]
->
interface Item {
id: number;
}
type Root = readonly Item[];Preguntas frecuentes
¿Qué construcciones de TypeScript genera?
Interfaces por defecto: una por cada forma de objeto. Los campos opcionales usan el marcador ?. Los arrays se convierten en T[]. Los arrays de tipos mixtos se convierten en una unión. Las cadenas con formatos reconocidos (por ejemplo, fechas ISO) se mantienen como string a menos que actives los tipos branded. Algunas páginas ofrecen alias 'type' en lugar de 'interface'.
¿Cómo se manejan los objetos anidados?
Cada forma anidada distinta obtiene su propia interface, nombrada según la ruta de la propiedad (User, UserAddress, UserPreferences). Si dos propiedades comparten la misma forma, el generador puede deduplicarlas o no según los ajustes; revisa la salida y consolida a mano si es necesario.
¿Las propiedades son obligatorias u opcionales?
Por defecto, las propiedades presentes en la muestra se marcan como obligatorias. Las propiedades que aparecen en algunos elementos del array pero no en otros se marcan como opcionales con `?`. Activa 'todas opcionales' si tu muestra es un ejemplo entre muchas formas posibles.
¿Cómo maneja null y undefined?
null en JSON se convierte en `null` en TypeScript (no undefined). Una propiedad que a veces es una cadena y a veces null se convierte en `string | null`. JSON no tiene undefined, por lo que el generador nunca emite `undefined` directamente.
¿Y los tipos unión y las uniones discriminadas?
Cuando un array contiene formas de objeto mixtas, el generador emite una unión de interfaces. No detecta automáticamente un campo discriminador; reescribe a mano como unión discriminada (por ejemplo, etiqueta 'kind') si quieres un estrechamiento de tipos exhaustivo.
¿Se sube el JSON?
No. La conversión se ejecuta en tu navegador con un parser JSON basado en JS y plantillas de cadena. El JSON pegado no sale de tu dispositivo.
¿Coincidirá con lo que realmente devuelve mi backend?
Solo en la medida en que lo haga la muestra. Valida siempre los datos en tiempo de ejecución contra un esquema (Zod, io-ts, Yup): los tipos de TypeScript se borran en tiempo de ejecución y no detectarán un backend que se desvíe del ejemplo.