Procesamiento de JSON en TypeScript: desde el análisis básico hasta la tipificación estricta
TypeScript, al ser una extensión de JavaScript, hereda todos los métodos integrados para trabajar con JSON, pero añade un potente sistema de tipos. Sin embargo, el JSON.parse() estándar devuelve el tipo any, lo que anula todas las ventajas de la tipificación estática. En este artículo, analizaremos cómo procesar JSON de forma segura y eficiente en TypeScript, utilizando tanto capacidades nativas como bibliotecas especializadas.
El problema del JSON.parse estándar
Consideremos un escenario típico:
const jsonString = '{"name":"Alice","age":30}';const user: any = JSON.parse(jsonString); // tipo anyconsole.log(user.name.toUpperCase()); // Error en tiempo de ejecución si name no existeTypeScript no te advertirá si la estructura del JSON no coincide con la esperada. La solución es usar una aserción de tipo (type assertion) o, mejor aún, validación en tiempo de ejecución.
Aserción de tipo básica (Type Assertion)
La forma más sencilla es indicar explícitamente el tipo del resultado:
interface User { id: number; name: string; email?: string;}
const raw = '{"id":1,"name":"Bob"}';const user = JSON.parse(raw) as User;console.log(user.name); // TypeScript sabe que es stringInconveniente: si el JSON llega con otros campos, el error solo ocurrirá en tiempo de ejecución. Esto no es seguro al trabajar con APIs externas.
Tipos recursivos y condicionales para JSON
TypeScript permite describir cualquier JSON mediante un tipo recursivo:
type JSONValue = | string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
function safeParse(json: string): JSONValue | Error { try { return JSON.parse(json) as JSONValue; } catch (e) { return new Error('JSON inválido'); }}Este enfoque garantiza que el resultado siempre será una estructura JSON válida, pero no verifica la forma específica.
Biblioteca Zod — validación de esquemas en tiempo de ejecución
Zod es la biblioteca más popular para la validación declarativa de datos en TypeScript. Permite describir un esquema y obtener el tipo automáticamente a partir de él.
Instalación
npm install zodEjemplo de uso
import { z } from 'zod';
// Describimos el esquemaconst UserSchema = z.object({ id: z.number().positive(), name: z.string().min(1), email: z.string().email().optional(), role: z.enum(['admin', 'user']).default('user'),});
// Inferimos el tipo a partir del esquematype User = z.infer<typeof UserSchema>;
// Análisis seguroconst result = UserSchema.safeParse(JSON.parse(rawJson));
if (result.success) { // result.data tiene el tipo User console.log(result.data.name);} else { console.error(result.error.format());}Zod verifica automáticamente los tipos, la obligatoriedad de los campos, los valores por defecto y devuelve errores detallados. Es la opción ideal para procesar datos de APIs REST o archivos de configuración.
Biblioteca io-ts — enfoque funcional
io-ts se basa en la programación funcional y la biblioteca fp-ts. Utiliza la composición de códecs (codecs) para decodificar/codificar datos.
Ejemplo
import * as t from 'io-ts';import { isRight } from 'fp-ts/lib/Either';
const UserCodec = t.type({ id: t.number, name: t.string, tags: t.array(t.string),});
const decoded = UserCodec.decode(JSON.parse(raw));
if (isRight(decoded)) { // decoded.right — objeto tipificado console.log(decoded.right.name);} else { // decoded.left — errores de validación console.log(decoded.left);}io-ts es más estricto y matemáticamente correcto, pero requiere comprender conceptos funcionales (Either, pipe).
También en la biblioteca
Remeda para TypeScript: guía completa con ejemplos prácticos
Caché en TypeScript: Redis y otras soluciones para Node.js
Configuración de aplicaciones Swift: biblioteca SwiftyConfig
Envío de correo electrónico en JavaScript (Node.js): Nodemailer, SendGrid, Mailgun