Introdução: «Type 'string | undefined' is not assignable to type 'string'» — uma dor familiar?
\n\nSe você programa em TypeScript há pelo menos uma semana, você com certeza já viu esta mensagem. Ela aparece no momento mais inesperado: você tem certeza de que a variável é uma string, mas o compilador insiste: «Ei, pode haver undefined aí!». Familiar?
Este erro é uma das perguntas mais frequentes no Stack Overflow (milhares de visualizações, dezenas de respostas). E não é que o TypeScript «seja burro». Pelo contrário: ele está salvando você de bugs em tempo de execução que poderiam derrubar a aplicação. Mas como explicar isso ao compilador? Como tornar o código seguro e legível ao mesmo tempo?
\n\nNeste artigo, vamos analisar:
\n- \n
- Por que ocorre o erro
Type 'string | undefined' is not assignable to type 'string'\n - 5 formas práticas de corrigi-lo (das simples às avançadas) \n
- Armadilhas típicas para iniciantes \n
- Quando usar
!(non-null assertion) e quando é melhor usar??(nullish coalescing) \n
Pronto? Vamos nessa!
\n\n1. Por que este erro ocorre no TypeScript?
\n\nEm JavaScript, uma variável pode ser undefined a qualquer momento. O TypeScript, especialmente com a flag strictNullChecks ativada, quer que você indique explicitamente: «Eu sei que pode haver um valor vazio aqui, e estou lidando com isso».
Veja um exemplo simples:
\n\nfunction getUsername(id: number): string {\n const user = users.find(u => u.id === id);\n return user.name; // Erro! user pode ser undefined\n}\n\n\nO método find() retorna User | undefined. Se o usuário não for encontrado — retornará undefined. O TypeScript vê isso e avisa: «Você está tentando atribuir string | undefined a string! Não pode!».
Isso não é um bug do TypeScript, é uma funcionalidade. Ele força você a pensar: «E se o usuário não existir? O que a função retornará? Uma string vazia? Lançará um erro?». E isso é correto.
\n\n2. 5 formas de corrigir o erro (do simples ao complexo)
\n\n2.1. Operador de asserção não-nula (!)
\n\nA forma mais rápida (e mais perigosa) é dizer ao TypeScript: «Cala a boca, eu sei o que estou fazendo».
\n\nfunction getUsername(id: number): string {\n const user = users.find(u => u.id === id);\n return user!.name; // ! — tenho certeza de que user não é undefined\n}\n\n\nQuando usar: Apenas se você tiver absoluta certeza de que o valor existe. Por exemplo, se você acabou de adicionar este usuário ao array e sabe com certeza que o find o encontrará.
Quando NÃO usar: Em 90% dos casos. É como desligar o airbag do carro — funciona, mas o risco é enorme.
\n\n2.2. Verificação com if (type guard)
\n\nA forma clássica e segura:
\n\nfunction getUsername(id: number): string {\n const user = users.find(u => u.id === id);\n if (user) {\n return user.name; // TypeScript sabe: dentro do bloco, user é definitivamente User\n }\n return 'Convidado'; // fallback\n}\n\n\nO TypeScript é inteligente: após a verificação if (user), ele «estreita» o tipo. Dentro do bloco, user é User, e não User | undefined.
2.3. Operador de encadeamento opcional (?.) com fallback
\n\nUma linha elegante para trabalhar com objetos aninhados:
\n\nfunction getUsername(id: number): string {\n const user = users.find(u => u.id === id);\n return user?.name ?? 'Convidado';\n}\n\n\nVamos detalhar:
\n- \n
user?.name— seuserforundefined, retornaundefined, sem lançar erro \n ?? 'Convidado'— se o valor à esquerda forundefinedounull, substituímos por 'Convidado' \