Tipos de dados em JavaScript e o operador typeof
Os sete primitivos e o object, o que typeof responde em cada um e por que typeof null devolve "object" desde 1995 — com o erro que isso provoca.
JavaScript tem oito tipos: sete primitivos — string, number, boolean,
undefined, null, symbol e bigint — e o object, que abriga tudo o mais.
Array não é um tipo separado. Função também não. Os dois são objetos.
O operador que responde qual é o tipo de um valor é o typeof. Ele é útil, é
rápido de digitar e tem duas respostas que confundem todo mundo na primeira vez:
typeof null é 'object' e typeof [] também. Esta lição mostra os oito tipos
rodando e explica exatamente onde o typeof ajuda e onde ele atrapalha.
O nome é a etiqueta; o tipo pertence ao que está dentro
Imagine potes etiquetados numa cozinha. A etiqueta total ajuda você a achar o
pote, mas quem decide o que pode ser feito é o conteúdo: açúcar pode entrar
numa conta; uma lista de compras precisa ser percorrida. Em JavaScript, a
variável é o nome e o tipo pertence ao valor guardado nela. Por isso o mesmo
nome pode apontar para um número agora e para uma string depois.
typeof é uma inspeção rápida daquilo que está no pote, não um detector
perfeito. Ele distingue primitivos muito bem, mas chama arrays, datas e null
de object por razões que veremos. Faça um teste antes da lista completa:
escreva três valores que você usa todo dia — um preço, um nome e um carrinho — e
preveja o typeof de cada um. Quando chegar ao array, não confunda a prateleira
“objetos” com o recipiente específico; para esse detalhe existe
Array.isArray.
Os oito tipos, um por linha
const nome = 'Teclado mecânico';
const preco = 289.9;
const disponivel = true;
const desconto = null;
let cupom;
const etiqueta = Symbol('pedido');
const unidadesVendidas = 9007199254740993n;
const cliente = { nome: 'Ana' };
console.log(typeof nome, typeof preco, typeof disponivel);
console.log(typeof desconto, typeof cupom, typeof etiqueta);
console.log(typeof unidadesVendidas, typeof cliente);Vale reparar em três coisas dessa saída.
preco é number e disponivel é boolean, sem surpresa — mas note que
JavaScript não tem tipo inteiro. 1 e 1.0 são o mesmo number, guardado
em ponto flutuante de 64 bits. É por isso que 0.1 + 0.2 não dá exatamente
0.3, e é por isso que existe o bigint: quando o número passa de
9.007.199.254.740.991, o number comum começa a perder precisão, e o sufixo n
resolve.
cupom foi declarado sem valor e vale undefined. desconto recebeu null de
propósito — e apareceu como object, que é o assunto de uma seção inteira mais
abaixo.
O symbol é o único que você provavelmente não vai criar nos primeiros meses.
Ele existe para gerar uma chave de propriedade que ninguém colide por acidente,
e aparece em código de biblioteca.
typeof responde bem, menos quando é objeto
console.log(typeof console.log);
console.log(typeof [289.9, 149.9]);
console.log(Array.isArray([289.9, 149.9]));
console.log(typeof new Date('2026-08-21'));Função devolve 'function', que nem é um dos oito tipos — é uma gentileza do
operador, porque saber se algo é chamável é pergunta frequente. Fora isso,
tudo que não é primitivo devolve 'object': array, data, expressão regular,
objeto comum. typeof não distingue nenhum deles.
Para array existe Array.isArray, que é a resposta certa e definitiva. Para o
resto, tem a técnica do fim desta lição.
Primitivo é copiado; objeto é compartilhado
Esta é a diferença que muda o comportamento do seu programa, mais do que o nome do tipo:
let precoA = 289.9;
let precoB = precoA;
precoB = 199;
const carrinhoA = { itens: 1 };
const carrinhoB = carrinhoA;
carrinhoB.itens = 5;
console.log(precoA, precoB);
console.log(carrinhoA.itens, carrinhoB.itens);Com número, precoB = precoA copiou o valor: mexer em um não toca no outro. Com
objeto, carrinhoB = carrinhoA copiou a referência — os dois nomes apontam
para o mesmo objeto na memória, e alterar por um lado altera pelo outro.
Não é pegadinha: é o que permite passar um objeto grande para uma função sem
duplicar a memória inteira. Mas é a origem do bug clássico de “mexi numa lista e a
outra mudou junto”. Quando você quiser mesmo uma cópia independente, use
structuredClone(objeto) ou o spread { ...objeto } para o primeiro nível.
typeof null devolve “object” — um bug de 1995
const desconto = null;
console.log(typeof desconto);
console.log(desconto === null);
console.log(desconto instanceof Object);null não é objeto: instanceof Object diz que não, e a especificação lista
null entre os primitivos. O 'object' vem da primeira implementação da
linguagem, em que cada valor carregava uma etiqueta de tipo nos bits mais baixos e
a etiqueta 000 significava “objeto”. O ponteiro nulo era todo zeros — e caiu na
mesma etiqueta.
Já houve proposta de corrigir. Foi rejeitada porque quebraria páginas antigas em funcionamento, e a compatibilidade retroativa é o compromisso mais duro do JavaScript. Hoje o comportamento é lei escrita na especificação.
O erro que esse bug provoca
Não é curiosidade acadêmica. Quem confia no typeof para decidir se pode acessar
uma propriedade escreve exatamente isto:
const pedido = { id: 4821, cupom: null };
if (typeof pedido.cupom === 'object') {
console.log('código do cupom:', pedido.cupom.codigo);
}TypeError: Cannot read properties of null (reading ‘codigo’) at file:///private/tmp/loja/l5-cupom.mjs:4:48 Node.js v24.16.0
O if passou porque typeof null é 'object', e a linha de dentro quebrou
porque null não tem propriedade nenhuma. A checagem honesta é
if (pedido.cupom) ou pedido.cupom?.codigo. Essa família de erro — a mais
comum da linguagem inteira — tem página própria:
TypeError: Cannot read properties of undefined.
typeof é o único operador que não quebra em nome inexistente
console.log(typeof configuracaoDaLoja);
console.log(configuracaoDaLoja);ReferenceError: configuracaoDaLoja is not defined at file:///private/tmp/loja/l5-typeof-livre.mjs:3:13 Node.js v24.16.0
A primeira linha imprimiu undefined sem reclamar de um nome que nunca foi
declarado. A segunda, com o mesmo nome, derrubou o programa. typeof é a única
operação que tolera identificador inexistente — foi feita assim para permitir
detectar recurso de ambiente antes de usá-lo.
Na prática moderna, o teste virou typeof window !== 'undefined' em código que
roda tanto no navegador quanto no servidor. Fora esse caso, typeof em nome que
pode não existir é sinal de que falta um import.
String tem método sem ser objeto
Se 'Teclado' é primitivo, como ele tem .toUpperCase()? Porque, no instante do
acesso, o motor embrulha o primitivo num objeto temporário, lê a propriedade e
joga o embrulho fora. Isso chama boxing, e o descarte é visível:
const nome = 'teclado mecânico';
console.log(nome.toUpperCase());
console.log(nome.length);
nome.marca = 'Club';TypeError: Cannot create property ‘marca’ on string ‘teclado mecânico’ at file:///private/tmp/loja/l5-boxing.mjs:6:12 Node.js v24.16.0
Ler funcionou; escrever não. Em modo estrito — o padrão em módulos — a tentativa
lança. Em script antigo, sem modo estrito, ela falha calada: a propriedade
some no embrulho descartado e nome.marca volta undefined na linha seguinte.
Erros comuns
Além do typeof null, dois tropeços que aparecem toda semana:
- Usar
typeofpara achar array.typeof lista === 'object'também é verdadeiro paranull, para{}e para uma data.Array.isArray(lista)é a pergunta certa. - Achar que
NaNé outro tipo. Não é:NaNénumber, o que faz todo sentido quando você lembra que ele nasce de uma conta numérica que deu errado.
console.log(typeof NaN);
console.log(typeof (289.9 * 'dois'));
console.log(typeof Infinity);NaN e as três formas de vazio da linguagem têm lição própria em
null, undefined e NaN, que é a próxima da
trilha.
Como checar tipo de verdade
Quando typeof não basta, existe um truque que devolve o nome interno do tipo,
o mesmo que a especificação usa:
const tipoReal = (valor) => Object.prototype.toString.call(valor).slice(8, -1);
console.log(tipoReal(null));
console.log(tipoReal(undefined));
console.log(tipoReal([289.9]));
console.log(tipoReal(new Date('2026-08-21')));
console.log(tipoReal(289.9));Na rotina do dia a dia, porém, a ordem é mais simples do que parece:
| o que você quer saber | use |
|---|---|
| é texto, número ou booleano | typeof valor === 'string' |
é null |
valor === null |
| é array | Array.isArray(valor) |
| é chamável | typeof valor === 'function' |
| tem valor útil | valor != null |
Guardar essa tabela poupa mais tempo do que decorar os oito tipos. E se você chegou aqui vindo da lição de variáveis em JavaScript, a conexão é direta: o nome não tem tipo, o valor tem — e é por isso que conferir o valor com console.log antes de usá-lo continua sendo o hábito mais barato da programação.
Prefere aprender em vídeo?
Tem uma aula sobre este assunto no nosso canal.
Perguntas frequentes
Quantos tipos existem em JavaScript?
Por que typeof null devolve object?
Como sei se uma variável é um array?
Qual a diferença entre valor primitivo e objeto na prática?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node 24.16.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- MDN — Tipos de dados e estruturas em JavaScript — developer.mozilla.org
- ECMAScript — The typeof Operator — tc39.es



