Introducción: El mito de la conversión de tipos «mágica»
\n\nTodo desarrollador de TypeScript, tarde o temprano, se enfrenta a esta situación: recibes un JSON del servidor, estás seguro de conocer su estructura, y haces un simple cast con as. Y… nada funciona. Los métodos de la clase faltan, los campos son undefined, y la depuración se convierte en una odisea.
La pregunta «How do I cast a JSON object to a TypeScript class?» es una de las más populares en Stack Overflow (decenas de miles de visitas). Y no es de extrañar. TypeScript es una extensión que solo existe durante la compilación. En tiempo de ejecución, tu «clase» es simplemente un plain JavaScript object.
\n\nEn este artículo, analizaremos los 5 errores más comunes y peligrosos que cometen los desarrolladores al trabajar con JSON y clases de TypeScript. Aprenderás cómo evitarlos y obtendrás soluciones listas para usar en código de producción.
\n\nError n.º 1: Usar as para una conversión «real»
\n\nLa trampa más común es pensar que la construcción jsonData as MyClass crea una instancia de la clase.
¿Qué sucede realmente?
\nEl operador as (o la sintaxis de angle-bracket) es una type assertion. Le dice al compilador: «Confía en mí, conozco el tipo». Pero en JavaScript no realiza ninguna magia.
class User {\n name: string = '';\n greet(): string {\n return `¡Hola, ${this.name}!`;\n }\n}\n\nconst rawData = JSON.parse('{"name": "Ana"}');\nconst user = rawData as User;\n\nconsole.log(user.name); // "Ana" — funciona\nconsole.log(user.greet()); // TypeError: user.greet is not a function\n\n\n¿Por qué? Porque rawData es un objeto común { name: 'Ana' }. No tiene el prototipo User.prototype y, por lo tanto, tampoco el método greet.
¿Cómo solucionarlo?
\nSiempre crea una instancia real de la clase. La forma básica es con Object.assign:
const user = Object.assign(new User(), rawData);\nconsole.log(user.greet()); // "¡Hola, Ana!"\n\n\nPero este método tiene matices, de los que hablaremos a continuación.
\n\nError n.º 2: Ignorar objetos y arrays anidados
\n\nUsas felizmente Object.assign, pero tus datos contienen estructuras anidadas. Y entonces comienza el infierno.
class Address {\n city: string = '';\n zip: string = '';\n}\n\nclass Company {\n name: string = '';\n address: Address = new Address();\n}\n\nconst data = JSON.parse('{"name": "TechCorp", "address": {"city": "Madrid", "zip": "28001"}}');\nconst company = Object.assign(new Company(), data);\n\nconsole.log(company.address.city); // "Madrid" — ¿suerte?\nconsole.log(company.address instanceof Address); // false!\n\n\nEl problema: address sigue siendo un objeto simple, no una instancia de Address. Si Address tuviera métodos o propiedades computadas, se perderían.
Solución: Conversión recursiva
\nEscribe una función fábrica o usa la librería class-transformer:
import { plainToClass } from 'class-transformer';\n\nconst company = plainToClass(Company, data);\nconsole.log(company.address instanceof Address); // true\n\n\nclass-transformer recorre recursivamente todos los campos y crea las instancias de clase correctas basándose en los decoradores @Type.
Error n.º 3: Pérdida de valores por defecto
\n\nTypeScript permite asignar valores por defecto a los campos directamente en la clase. Pero al hacer «cast» del JSON, estos valores pueden ser sobrescritos con undefined.
class Config {\n theme: string = 'light';\n fontSize: number = 14;\n language: string = 'es';\n}\n\nconst partialData = JSON.parse('{"theme": "dark"}');\nconst config = Object.assign(new Config(), partialData);\n\nconsole.l