TypeError: Cannot read properties of undefined (reading 'x')é o erro de tempo de execução mais comum em JavaScript. A mensagem é precisa quando você aprende a lê-la, e a correção é quase sempre um dos cinco padrões. Este guia aborda como localizar a causa rapidamente e como evitar que ela se repita.
📋 Table of Contents
- O que o erro realmente significa
- Causa 1: dados assíncronos lidos antes de chegarem
- Causa 2: o formato da resposta da API não é o que você presumiu
- Causa 3: métodos de pesquisa de array que não encontraram nada
- Causa 4: Desestruturando um objeto indefinido
- Causa 5:this Perdeu a ligação
- As ferramentas que o impedem
- Método de depuração
- Prevenindo Estruturalmente
- Perguntas Frequentes
- Conclusão
O que o erro realmente significa
Você tentou ler uma propriedade de algo que éundefined. A parte entre parênteses informa qual propriedade você tentou ler.
const user = undefined;
console.log(user.name);
// TypeError: Cannot read properties of undefined (reading 'name')
A visão crítica:o problema não é a propriedade, é a coisa antes do ponto. Quando você vê(reading 'name'), o bug é que tudo o que deveria conter o objeto do usuário éundefined. Todo mundo perde tempo depurandoname quando eles deveriam estar perguntando por quêuser está vazio.
Em uma corrente, trabalhe da esquerda para a direita para encontrar o primeiro elo indefinido.
const response = { data: { items: [] } };
console.log(response.data.results.length);
// TypeError: Cannot read properties of undefined (reading 'length')
// 'results' does not exist on data, so response.data.results is undefined.
Causa 1: dados assíncronos lidos antes de chegarem
De longe a causa mais frequente em aplicações reais. O estado começa vazio, a renderização é executada e a busca ainda não foi resolvida.
function Profile({ userId }) {
const [user, setUser] = useState(); // undefined on first render
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser);
}, [userId]);
return <h1>{user.name}</h1>; // throws on the very first render
}
Corrija inicializando com um valor vazio sensato e protegendo a renderização.
function Profile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
setLoading(true);
fetch(`/api/users/${userId}`)
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
})
.then(data => { if (!cancelled) setUser(data); })
.catch(err => { if (!cancelled) console.error(err); })
.finally(() => { if (!cancelled) setLoading(false); });
return () => { cancelled = true; };
}, [userId]);
if (loading) return <p>Loading…</p>;
if (!user) return <p>User not found.</p>;
return <h1>{user.name}</h1>;
}
Ocancelled flag também evita um segundo bug comum: uma resposta lenta de umuserId substituindo os dados mais recentes após a alteração do suporte.
Causa 2: o formato da resposta da API não é o que você presumiu
Você escreveudata.items mas a API retorna{ results: [...] }, ou envolve tudo em{ data: { ... } }. É especialmente fácil errar com o Axios, que adiciona seu própriodata wrapper na parte superior do corpo da resposta.
// Axios puts the response body in .data — so the payload is often data.data
const response = await axios.get('/api/users');
console.log(response.data.users); // correct
console.log(response.users); // undefined -> throws downstream
Registre toda a resposta antes de indexá-la. Umconsole.log(JSON.stringify(response, null, 2)) responde à pergunta imediatamente, onde a adivinhação não.
Causa 3: métodos de pesquisa de array que não encontraram nada
find retornaundefined quando nenhum elemento corresponde, e esta é a fonte mais comum do erro no código de manipulação de lista.
const users = [{ id: 1, name: 'Ada' }];
const match = users.find(u => u.id === 99);
console.log(match.name);
// TypeError: Cannot read properties of undefined (reading 'name')
Sempre trate o resultado como possivelmente ausente.
const match = users.find(u => u.id === 99);
if (!match) {
return null; // or throw a clear domain error
}
console.log(match.name);
// Or with optional chaining when a missing value is acceptable:
console.log(match?.name ?? 'Unknown user');
O mesmo se aplica adocument.querySelector, que retornanull quando nada corresponde, e paraMap.get eArray.at.
Causa 4: Desestruturando um objeto indefinido
A desestruturação lê propriedades, então é lançada exatamente pelo mesmo motivo – apenas com uma linha de pilha menos óbvia.
function greet({ name }) {
return `Hello ${name}`;
}
greet();
// TypeError: Cannot destructure property 'name' of 'undefined'
Dê um padrão ao parâmetro para que a desestrutura sempre tenha um objeto com o qual trabalhar.
function greet({ name = 'friend' } = {}) {
return `Hello ${name}`;
}
greet(); // "Hello friend"
greet({ name: 'Ada' }); // "Hello Ada"
Causa 5:this Perdeu a ligação
Quando um método é passado como retorno de chamada,this não é mais o objeto, portanto, todas as propriedades lidas nele falham.
class Counter {
constructor() { this.count = 0; }
increment() { this.count++; } // 'this' is undefined when detached
}
const c = new Counter();
button.addEventListener('click', c.increment);
// TypeError: Cannot read properties of undefined (reading 'count')
Vincule-o ou use um campo de classe com uma função de seta, que capturathis lexicalmente.
class Counter {
count = 0;
increment = () => { this.count++; }; // arrow field — always bound
}
const c = new Counter();
button.addEventListener('click', c.increment); // works
As ferramentas que o impedem
Encadeamento opcional curto-circuitos paraundefined em vez de jogar.
const city = user?.address?.city; // undefined, no throw
const first = users?.[0]?.name; // works on arrays too
const result = api.getUser?.(id); // and on possibly-missing methods
Coalescência nula fornece um substituto apenas paranull eundefined, ao contrário de|| que também substitui0 e strings vazias.
const count = data?.count ?? 0; // 0 stays 0
const wrong = data?.count || 0; // a real 0 becomes 0 anyway, but '' becomes 0 too
Use encadeamento opcional onde um valor ausente for genuinamente válido. Não espalhe-o por toda parte para silenciar erros – seuser deve sempre existir nesse ponto, ocultar sua ausência transforma um bug barulhento em um bug silencioso que surge mais tarde sem nenhum rastreamento de pilha.
Método de depuração
Quando o erro aparecer, siga esta sequência.
- Leia o nome da propriedade entre parênteses. O bug está na expressãoantes aquela propriedade.
- Abra o rastreamento de pilha e clique no quadro superior do seu próprio código, ignorando os quadros da biblioteca.
- Defina um ponto de interrupção nessa linha e inspecione a expressão que contém, não a propriedade.
- Percorra a corrente da esquerda para a direita para encontrar o primeiro elo indefinido.
- Pergunte por que esse valor está vazio – uma busca não foi resolvida, uma pesquisa falhou, um suporte nunca foi aprovado?
Na produção, os mapas de origem são essenciais. Sem eles, o rastreamento aponta para o código minificado e esse processo é impossível.
Prevenindo Estruturalmente
Datilografado captura a maioria deles em tempo de compilação, especialmente comstrictNullChecks habilitado. Isso força você a lidar com o caso indefinido antes da execução do código.
function getName(user: User | undefined): string {
// Error: 'user' is possibly 'undefined' — caught before runtime
return user.name;
}
Valide nos limites. Analise as respostas da API com um validador de esquema como Zod para que uma forma inesperada falhe imediatamente com uma mensagem clara, em vez de propagar três camadas indefinidas em seu código de renderização.
Retorna coleções vazias, não indefinidas. Uma função que retorna[] em vez deundefined permite que os chamadores mapeiem o resultado incondicionalmente.
Perguntas Frequentes
P: Qual é a diferença entre isso e “Não é possível ler propriedades de nulo”?
R: Somente o valor. undefined geralmente significa que uma variável nunca foi atribuída ou que uma propriedade não existe; null geralmente significa algo explicitamente definido como vazio. A abordagem de depuração é idêntica.
P: Devo apenas adicionar encadeamento opcional em todos os lugares?
R: Não. Use-o onde um valor for legitimamente opcional. Usá-lo para silenciar um erro que você não entende converte uma falha com rastreamento de pilha em um comportamento errado sem nenhum rastreamento.
P: Por que funciona localmente, mas falha na produção?
R: Geralmente tempo ou dados. As APIs locais respondem mais rapidamente, ocultando as condições de corrida; e os dados de produção contêm formas que seus dados de teste não contêm, como registros com campos opcionais ausentes.
P: Como encontro o erro quando o rastreamento de pilha mostra apenas o código da biblioteca?
R: Habilite os mapas de origem e use a “Lista de ignorados” no Chrome DevTools para ocultar os quadros da estrutura para que o quadro visível mais alto seja seu próprio código.
P: O TypeScript elimina esse erro completamente?
R: Não. Ele elimina o código que pode verificar, mas os dados ultrapassam os limites do tempo de execução — respostas da API, análise JSON,any casts — ainda pode ser indefinido em tempo de execução. Valide dados externos mesmo em TypeScript.
Conclusão
CorreçãoCannot read properties of undefined é mecânico quando você conhece a regra:o erro está na expressão antes da propriedade, não na propriedade em si. Verifique as cinco causas comuns: leitura de dados assíncronos muito cedo, formato de API incompatível,find que não correspondia a nada, desestruturando um objeto ausente e um objeto perdidothis vinculativo. Em seguida, evite a recorrência com encadeamento opcional onde os valores são genuinamente opcionais, TypeScript comstrictNullCheckse validação de esquema em cada limite onde dados externos entram em seu sistema.
🔗 Share this article
✍️ Leave a Comment