O que é e como funciona na prática
O objeto com que é um conceito que aparece sempre que você precisa lidar com algo genérico em programação orientada a objetos — um container vazio que recebe propriedades dinamicamente. A maioria dos tutoriais explica isso como "um objeto sem estrutura definida". Na prática, é bem mais chato do que isso soa. Eu lido com isso há anos, principalmente em projetos onde a estrutura dos dados não é fixa desde o início. No começo, você trata como um objeto normal, depois percebe que não tem definição de tipo e começa a receber erros estranhos de compilação ou, pior, bugs silenciosos em tempo de execução.
Por que o objeto com que é problemático
O problema central não é a definição em si, mas o que acontece quando você passa esse objeto para uma função que espera tipos concretos. Digo isso porque já perdi horas rastreando um bug onde um campo esperava ser string e vinha nulo porque o objeto tinha sido populado de forma diferente no fluxo anterior. O código compilava normalmente. Só falhava na runtime. O que a maioria dos materiais não mostra é que o verdadeiro custo do objeto com que não está na escrita — está na manutenção. Seis meses depois, você ou outro desenvolvedor vai precisar entender por que aquele campo foi nomeado de uma certa forma, quando foi adicionado, e qual é o contrato esperado. Sem tipagem forte, isso vira arqueologia.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Como lidar de forma mais previsível
A solução que eu adoto hoje é simples e evita muito sofrimento. Antes de passar um objeto genérico para qualquer camada do sistema, eu aplico um mapeamento explícito. Não é sobre adicionar annotations ou decorators bonitos — é sobre criar uma função de transformação que recebe o objeto bruto e retorna um objeto com tipos definidos. Isso custa alguns minutos extras na implementação, mas economiza horas de debugging depois. Um detalhe importante que pouca gente menciona: se você estiver usando TypeScript, o tipo `any` é o inimigo quando se trata de objetos com que. Todo uso de `any` em um objeto é um risco calculado. A alternativa não é fugir completamente — é usar `unknown` e fazer validação explicita antes de tratar como qualquer coisa específica. Parece trabalho a mais, mas o ganho em segurança é real.
Um caso específico que enfrentei recentemente
No último projeto, precisei consumir uma API que retornava objetos com campos opcionais que variavam conforme o tipo de produto. Tinha campos que apareciam apenas para produtos físicos e outros apenas para digitais. Meu primeiro impulso foi criar interfaces gigantes com tudo opcional. Funcionou, mas ficou ilegível em pouco tempo. A solução que funcionou foi criar um type guard. Uma função que recebe o objeto genérico, verifica os campos presentes e retorna verdadeiro ou falso sobre qual tipo concreto aquele objeto representa. Depois disso, o resto do código trabalha com tipos known e o TypeScript faz o trabalho pesado. O código fica mais verboso na chamada, mas muito mais claro em cada do que seria com casts manuais.
Se você está começando agora com esse conceito, o conselho mais honesto que posso dar é: não tente evitar completamente. Objeto com que vai aparecer, independente da linguagem ou framework. O importante é ter uma estratégia definida para quando ele surgir — seja validação, type guards, ou mapeamento explícito. Tentar esconder o problema só adia o custo.