Introdução: por que este tópico explodiu no Stack Overflow?
\nSe você já escreveu em TypeScript, certamente já enfrentou o dilema: unknown ou any? A pergunta, que acumulou milhares de visualizações no Stack Overflow, não perde a relevância em 2025. Parece que ambos os tipos permitem armazenar qualquer coisa — então qual é a diferença?
Imagine que você está construindo uma casa. any é uma porta escancarada para todos, incluindo ladrões. unknown é uma porta com fechadura e olho mágico: você primeiro verifica quem chegou, depois deixa entrar. Neste artigo, vamos entender por que unknown se tornou o padrão ouro de segurança em TypeScript, e any — o mal que às vezes é justificado.
Não vamos apenas recontar a documentação. Vamos mostrar casos reais da prática em 2025, analisar as melhores práticas e dar um algoritmo claro de escolha. Vamos lá!
\n\nO que é any e por que todos o temem?
\n\nany é o tipo mais "flexível" em TypeScript. Ele literalmente diz ao compilador: "Desligue o sistema de tipos, eu sei o que estou fazendo". Parece um superpoder, mas na prática é uma bomba-relógio.
Exemplo: como any quebra os tipos
\nfunction processUser(user: any) {\n console.log(user.name.toUpperCase()); // Erro em tempo de execução se user for null\n}\n\nprocessUser(null); // TypeError: Cannot read property 'toUpperCase' of null\n\nO compilador TypeScript nem sequer avisará você sobre isso! any desativa todas as verificações, e o erro só aparecerá em produção. Em 2025, com projetos cada vez mais complexos, essa abordagem é o caminho para o caos.
Quando any ainda é útil?
\n- \n
- Migração de JavaScript: ao reescrever um projeto antigo,
anyé uma muleta temporária. \n - Dados dinâmicos: por exemplo, respostas de APIs externas cuja estrutura muda. \n
- Testes: em mocks, às vezes é mais fácil usar
anydo que descrever tipos complexos. \n
Mas lembre-se: any é como um cartão de crédito com limite infinito. É conveniente, até a conta chegar.
Unknown: o guardião rigoroso na entrada
\n\nunknown surgiu no TypeScript 3.0 como uma alternativa segura ao any. Ele também pode conter qualquer valor, mas proíbe trabalhar com ele sem uma verificação explícita. É um tipo-contêiner que exige verificação.
Exemplo: unknown em ação
\nfunction processUser(user: unknown) {\n // Erro de compilação! A propriedade 'name' não existe no tipo 'unknown'\n // console.log(user.name.toUpperCase()); \n \n // É necessária uma verificação\n if (user && typeof user === 'object' && 'name' in user) {\n const typedUser = user as { name: string };\n console.log(typedUser.name.toUpperCase()); // Tudo ok\n }\n}\n\nprocessUser({ name: "Alice" }); // ALICE\nprocessUser(null); // Não vai quebrar\n\nNotou a diferença? unknown não permite que você atire no próprio pé. Você é obrigado a verificar o tipo antes de usar. Isso é a tipagem segura.
Comparação any vs unknown em tabela
\n\nPara fixar o conteúdo, vamos ver as principais diferenças:
\n\n| Critério | \nany | \nunknown | \n
|---|---|---|
| Atribuição de qualquer valor | \n✅ Sim | \n✅ Sim | \n
| Acesso a propriedades sem verificação | \n✅ Sim | \n❌ Não | \n
| Atribuição a outro tipo | \n✅ Qualquer um | \n❌ Apenas any ou unknown | \n
| Proteção contra erros em tempo de execução | \n❌ Não | \n✅ Sim (exige verificação) | \n
Como você pode ver, unknown vence