Introducción: JSON y TypeScript — la pareja ideal para trabajar con datos
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos que se ha convertido en el estándar de facto para la comunicación entre cliente y servidor, así como para almacenar configuraciones y transmitir información estructurada. TypeScript, al ser un superconjunto fuertemente tipado de JavaScript, proporciona herramientas potentes para trabajar con JSON de forma segura y predecible. En este artículo, analizaremos en la práctica cómo parsear (convertir una cadena JSON en un objeto) y serializar (convertir un objeto en una cadena JSON) datos en TypeScript, evitando errores típicos y aprovechando las capacidades del sistema de tipos.
Fundamentos: JSON.parse() y JSON.stringify() en TypeScript
TypeScript hereda completamente los métodos integrados de JavaScript para trabajar con JSON: JSON.parse() y JSON.stringify(). Sin embargo, su uso en un entorno fuertemente tipado requiere un enfoque especial.
JSON.parse() — de cadena a objeto
El método JSON.parse() toma una cadena JSON y devuelve un objeto. En TypeScript, el resultado por defecto tiene el tipo any, lo que nos priva de todas las ventajas de la tipificación. Veamos un ejemplo:
const jsonString = '{"name": "TypeScript", "version": 5.3}';const parsed: any = JSON.parse(jsonString);console.log(parsed.name); // Funciona, pero no hay autocompletado ni verificación de tiposPara obtener un resultado tipificado, use la aserción de tipos (type assertion):
interface Language { name: string; version: number;}
const jsonString = '{"name": "TypeScript", "version": 5.3}';const parsed = JSON.parse(jsonString) as Language;console.log(parsed.name.toUpperCase()); // ¡El autocompletado funciona!JSON.stringify() — de objeto a cadena
JSON.stringify() serializa un objeto en una cadena JSON. TypeScript verifica que el objeto pasado sea válido para la serialización (que no contenga funciones, undefined, Symbol, etc.).
interface User { id: number; name: string; isActive: boolean;}
const user: User = { id: 1, name: "Alice", isActive: true };const jsonString = JSON.stringify(user);console.log(jsonString); // '{"id":1,"name":"Alice","isActive":true}'Técnicas avanzadas: tipificación y manejo de errores
En la práctica, trabajar con JSON rara vez es perfecto. Los datos pueden llegar del servidor en un formato inesperado, contener campos adicionales o faltar campos obligatorios. Veamos cómo TypeScript ayuda a manejar estos problemas.
Creación de una función genérica para análisis seguro
Escribamos una función universal que tome una cadena JSON y devuelva un resultado tipificado con manejo de errores:
function safeParse<T>(json: string): T | null { try { return JSON.parse(json) as T; } catch (error) { console.error("Error al analizar JSON:", error); return null; }}
// Usointerface Product { id: number; title: string; price: number;}
const rawData = '{"id": 101, "title": "Laptop", "price": 999.99}';const product = safeParse<Product>(rawData);if (product) { console.log(product.title); // "Laptop"}Validación de datos con protectores de tipo personalizados
Incluso después de la aserción de tipo as T, TypeScript no verifica que los datos realmente correspondan a la interfaz. Para la validación en tiempo de ejecución, use type guards:
function isProduct(obj: any): obj is Product { return ( typeof obj === 'object' && obj !== null && typeof obj.id === 'number' && typeof obj.title === 'string' && typeof obj.price === 'number' );}
const rawData = '{"id": "abc", "title": "Phone", "price": 599}';const parsed = JSON.parse(rawData);if (isProd