Menu

Coerção de Tipos em JavaScript: Implícita vs Explícita

Entenda como o JavaScript converte valores entre tipos: as regras de coerção implícita que pegam todo mundo de surpresa, as conversões explícitas que você deveria preferir e quando cada uma entra em ação.

Dois tipos de coerção

O JavaScript é flexível com tipos. Quando um operador recebe um valor do tipo "errado", a linguagem não dispara erro — ela converte. Essa conversão se chama coerção, e ela aparece de duas formas:

  • Explícita — quando você pede: Number("42"), String(99), Boolean(value).
  • Implícita — quando um operador dispara a conversão sem você escrever nada: "5" - 2, "" == 0, if (value).

As duas acabam chamando as mesmas regras de conversão por baixo dos panos. A diferença é quem decidiu converter: você ou a linguagem. Quase todo resultado confuso do JavaScript — "5" + 1 === "51", [] == false, null == undefined — vem de uma coerção implícita que te pega desprevenido.

index.js
Output
Click Run to see the output here.

O modelo mental é simples: se você escreve Number(...) ou String(...), você sabe exatamente o que está pedindo. Quando não escreve, cada operador tem a sua própria opinião sobre o que fazer — e é justamente aí que os bugs se escondem.

Os três tipos de destino na coerção

A coerção de tipos em JavaScript sempre converte para um de três tipos primitivos: string, number ou boolean. (Existe um quarto, o bigint, mas ele nunca recebe coerção automática a partir de outros tipos.) Todo o resto das regras decorre de qual desses alvos o operador está mirando.

index.js
Output
Click Run to see the output here.

A coerção para string é a mais camarada — todo valor tem uma forma em string. Repare que objetos viram aquele "[object Object]" que não ajuda em nada, e é por isso que dar log em um objeto concatenado com string ("user: " + user) quase nunca mostra o que você queria ver. Nesses casos, prefira JSON.stringify ou template literals com os campos específicos.

Coerção para Number

Já a coerção para número é mais rígida. A string precisa realmente ter cara de número, senão você recebe NaN:

index.js
Output
Click Run to see the output here.

As surpresas entre parênteses são justamente as que vale a pena decorar:

  • String vazia e strings só com espaços viram 0, e não NaN.
  • null vira 0, mas undefined vira NaN.
  • Array vazio vira 0; array com um único elemento força a coerção desse elemento; array com vários elementos vira NaN.

Quando você precisa extrair um número de uma string que tem caracteres extras, use parseInt ou parseFloat no lugar de Number:

index.js
Output
Click Run to see the output here.

Sempre passe a base (10) para o parseInt. Sem ela, strings que começam com "0x" são interpretadas como hexadecimal, o que quase nunca é o que você quer.

Coerção para Boolean

A coerção para booleano é a mais simples das três. Existe uma pequena lista de valores que viram false — todo o resto vira true.

Os valores falsy são:

  • false
  • 0, -0, 0n
  • "" (string vazia)
  • null
  • undefined
  • NaN

É isso. Qualquer outro valor — incluindo "false", "0", [] e {} — é truthy.

index.js
Output
Click Run to see the output here.

Os resultados de array vazio e objeto vazio costumam pegar de surpresa quem vem do Python, onde coleções vazias são falsy. No JavaScript, elas são truthy — se você quer saber "esse array está vazio?", verifique explicitamente com arr.length === 0.

A coerção para booleano acontece sempre que um valor aparece onde se espera um booleano: if (...), while (...), o ternário ? : e os operadores lógicos &&, ||, !.

O operador + é um caso à parte

A maioria dos operadores aritméticos força seus operandos para número. Já o + é diferente: se qualquer um dos lados for uma string, o + faz concatenação de strings. Caso contrário, faz soma numérica.

index.js
Output
Click Run to see the output here.

A avaliação acontece da esquerda para a direita. Em 1 + 2 + "3", primeiro o JS calcula 1 + 2 = 3 e depois 3 + "3" = "33". Já "1" + 2 + 3 começa como string e segue como string até o fim: vira "12" e depois "123".

É por isso que montar strings com + é furada. Com template literals, esse problema some:

index.js
Output
Click Run to see the output here.

O template literal avalia count + 1 como uma expressão numérica isolada e só depois interpola o resultado. Sem coerção inesperada no caminho.

Prefira conversões explícitas

Quando você precisa converter um tipo, deixe isso claro no código. Custa alguns caracteres a mais e elimina qualquer ambiguidade para quem for ler depois:

index.js
Output
Click Run to see the output here.

A mesma ideia vale para booleanos. O !!value funciona e é bem comum, mas o Boolean(value) deixa explícito o que está acontecendo:

index.js
Output
Click Run to see the output here.

Uma regra razoável: use conversões explícitas na lógica da sua aplicação e reserve as formas curtas (+x, !!x) para situações em que a concisão importa e a intenção já fica clara pelo contexto.

O operador == depende muito da coerção

Os operadores de igualdade são a maior fonte de surpresas envolvendo coerção de tipos em JavaScript. O == faz coerção antes de comparar; o === não.

index.js
Output
Click Run to see the output here.

Cada true do exemplo acima é o resultado de uma cadeia de coerção de vários passos que a maioria dos devs não consegue recitar de cabeça. E aí está o problema — código que funciona por acidente é código que vai quebrar mais tarde. Vamos mergulhar nas regras completas de igualdade na próxima página; por enquanto, fica a dica: use === por padrão, e só recorra ao == para o idioma específico x == null (que pega tanto null quanto undefined).

Juntando tudo na prática

Um exemplo trabalhado mostrando onde a coerção ajuda e onde ela atrapalha:

index.js
Output
Click Run to see the output here.

Repare na segunda chamada. Number("") devolve 0, e não NaN — então parsePrice("") acaba retornando 0, o que provavelmente não é o que quem usa essa função espera. Se a ideia é rejeitar entrada vazia, adicione uma verificação explícita:

index.js
Output
Click Run to see the output here.

Saber quais valores viram 0 e quais viram NaN é exatamente o tipo de detalhe que evita um bug chato lá na frente.

O que levar dessa aula

  • A coerção de tipos em JavaScript converte valores para string, número ou booleano dependendo do operador.
  • + com qualquer string vira concatenação; todos os outros operadores aritméticos convertem para número.
  • Os valores falsy são uma lista curta e fixa — decore. Todo o resto é truthy, inclusive [] e {}.
  • Number("") é 0, Number([]) é 0, Number(null) é 0 — mas Number(undefined) é NaN. Isso aparece em bugs reais.
  • Prefira Number(x), String(x) e Boolean(x) no lugar de truques implícitos espertinhos. Seu eu do futuro agradece.

A seguir: operadores de igualdade

Tudo que a coerção faz nas comparações mora dentro do ==. Na próxima página a gente compara ==, === e Object.is, vê o único caso em que o == ainda é útil, e por que os linters já marcam a forma frouxa por padrão.

Perguntas frequentes

O que é coerção de tipos em JavaScript?

Coerção de tipos é quando o JavaScript converte automaticamente um valor de um tipo para outro — um número virando string, uma string virando número, ou qualquer coisa virando boolean. Isso acontece de forma implícita quando operadores como +, == ou if recebem um valor que não é do tipo esperado, e de forma explícita quando você mesmo chama Number(x), String(x) ou Boolean(x).

Qual a diferença entre coerção implícita e explícita?

A coerção explícita é quando você chama uma função de conversão de propósito: Number("42"), String(99), Boolean(valor). Já a implícita é quando o próprio operador dispara a conversão pelas suas costas: "5" - 2 devolve 3, mas "5" + 2 devolve "52". A explícita é legível e previsível; a implícita é a origem da maioria dos bugs do tipo "por que isso virou NaN?".

Como converter string para número em JavaScript?

Use Number("42") para uma conversão estrita (retorna NaN se a string não for um número válido), ou parseInt("42px", 10) / parseFloat("3.14em") quando você quer extrair o número do começo de uma string mais bagunçada. O operador unário + (+"42") faz o mesmo que Number(), mas passa despercebido quando você bate o olho rápido no código.

Por que [] + [] retorna uma string vazia?

O operador + não tem uma operação numérica que faça sentido entre dois arrays, então o JavaScript converte os dois para string. Arrays viram string juntando os elementos com vírgula, e um array vazio vira "". Ou seja, [] + [] acaba como "" + "", que dá "". É uma curiosidade divertida — e um ótimo argumento para nunca usar + com valores que não são primitivos.

Aprenda a programar com o Coddy

COMEÇAR