JSON em TypeScript: 5 erros fatais ao fazer cast e como corrigi-los

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: O mito da conversão de tipos "mágica"

\n\n

Todo desenvolvedor TypeScript, mais cedo ou mais tarde, se depara com a seguinte situação: você recebe um JSON do servidor, tem certeza de que conhece sua estrutura e faz um simples cast usando as. E… nada funciona. Os métodos da classe estão ausentes, os campos estão undefined, e a depuração se transforma em uma missão.

\n\n

A pergunta "How do I cast a JSON object to a TypeScript class?" é uma das mais populares no Stack Overflow (dezenas de milhares de visualizações). E não é surpresa. TypeScript é uma camada extra que existe apenas durante a compilação. Em tempo de execução, sua "classe" é apenas um objeto JavaScript simples.

\n\n

Neste artigo, vamos analisar os 5 erros mais comuns e perigosos que os desenvolvedores cometem ao trabalhar com JSON e classes TypeScript. Você aprenderá como evitá-los e obterá soluções prontas para código em produção.

\n\n

Erro nº 1: Usar as para uma conversão "real"

\n\n

A armadilha mais comum é pensar que a construção jsonData as MyClass cria uma instância da classe.

\n\n

O que realmente acontece?

\n

O operador as (ou a sintaxe de angle-bracket) é uma afirmação de tipo. Ele diz ao compilador: "Confie em mim, eu sei o tipo". Mas em JavaScript, ele não realiza nenhuma mágica.

\n\n
class User {\n    name: string = '';\n    greet(): string {\n        return `Olá, ${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 é um objeto comum { name: 'Ana' }. Ele não tem o protótipo User.prototype e, portanto, não tem o método greet.

\n\n

Como corrigir?

\n

Sempre crie uma instância real da classe. A maneira básica é usar Object.assign:

\n\n
const user = Object.assign(new User(), rawData);\nconsole.log(user.greet()); // "Olá, Ana!"\n
\n\n

Mas este método tem nuances, que discutiremos a seguir.

\n\n

Erro nº 2: Ignorar objetos e arrays aninhados

\n\n

Você usa Object.assign felizmente, mas seus dados contêm estruturas aninhadas. E aí começa o inferno.

\n\n
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": "Moscou", "zip": "101000"}}');\nconst company = Object.assign(new Company(), data);\n\nconsole.log(company.address.city); // "Moscou" — sorte?\nconsole.log(company.address instanceof Address); // false!\n
\n\n

Problema: address permaneceu um objeto simples, não uma instância de Address. Se Address tiver métodos ou propriedades computadas, eles serão perdidos.

\n\n

Solução: Conversão recursiva

\n

Escreva uma função fábrica ou use a biblioteca class-transformer:

\n\n
import { plainToClass } from 'class-transformer';\n\nconst company = plainToClass(Company, data);\nconsole.log(company.address instanceof Address); // true\n
\n\n

class-transformer percorre recursivamente todos os campos e cria as instâncias corretas das classes com base nos decoradores @Type.

\n\n

Erro nº 3: Perda de valores padrão

\n\n

TypeScript permite definir valores padrão para campos diretamente na classe. Mas ao "converter" JSON, esses valores podem ser sobrescritos por undefined.

\n\n
class Config {\n    theme: string = 'light';\n    fontSize: number = 14;\n    language: string = 'pt';\n}\n\nconst partialData = JSON.parse('{"theme": "dark"}');\nconst config = Object.assign(new Config(), partialData);\n\nconsole.l                

Blogs

Book Recommendations