Conversão de Tipos em JavaScript
A conversão de tipos é a parte mais propensa a erros do JavaScript. Um número digitado em um formulário? Acontece que é uma string! "5" + 3 resulta em "53" em vez de 8 — todo iniciante encontra essas "surpresas".
📖 Resumo
Por Que a Conversão de Tipos Importa
Valores de input de formulários HTML são sempre strings, mesmo com type="number". Você deve converter os tipos antes de fazer contas, ou os resultados serão imprevisíveis.
<div id="demo"></div>
<script>
const input = "42";
const resultado = input + 8;
document.getElementById("demo").textContent = 'input + 8 = ' + resultado + ' (tipo: ' + typeof resultado + ')';
</script>
Conversão Explícita: String(), Number(), Boolean()
Chamar funções de conversão explicitamente deixa sua intenção clara — esta é a abordagem recomendada:
| Conversão | Sintaxe | Exemplo |
|---|---|---|
| Para string | String(valor) |
String(123) → "123" |
| Para número | Number(valor) |
Number("42") → 42 |
| Para booleano | Boolean(valor) |
Boolean(0) → false |
Conversão Implícita: Concatenação com + e Comparação com ==
O motor JavaScript realiza conversão automática de tipos que frequentemente produz resultados inesperados:
- Operador
+: se um lado for string, o outro é convertido para string para concatenação - Comparação
==: converte tipos antes de comparar, com regras complexas difíceis de lembrar
<script>
console.log("5" + 3); // "53" (número 3 convertido para string)
console.log("5" - 3); // 2 (string "5" convertida para número)
console.log("" == 0); // true (string vazia convertida para 0)
console.log(null == undefined); // true
</script>
Erros Comuns
Estes são erros de alta frequência em entrevistas e no desenvolvimento real:
<script>
console.log("5" + 3); // "53" + concatena quando vê uma string
console.log("5" - 3); // 2 - só faz subtração, converte string para número
console.log("5" * 3); // 15 * também converte para número
console.log(true + 1); // 2 true converte para 1
console.log(false + 1); // 1 false converte para 0
console.log("" + 0); // "0" número converte para string
console.log("" == 0); // true ambos os lados convertem para números
console.log(null == 0); // false null só é igual a undefined
console.log("0" == false); // true ambos convertem para 0
</script>
Lembre desta regra: + concatena quando encontra uma string; todos os outros operadores aritméticos convertem strings para números.
Regras de Conversão do Number()
| Entrada | Resultado |
|---|---|
Number("42") |
42 |
Number("3.14") |
3.14 |
Number("") |
0 (string vazia → 0, pegadinha clássica) |
Number(" ") |
0 (string só com espaço → 0) |
Number("42px") |
NaN (contém caracteres não numéricos → NaN) |
Number(true) |
1 |
Number(false) |
0 |
Number(null) |
0 |
Number(undefined) |
NaN |
String vazia converte para 0 em vez de NaN — esse design já enganou incontáveis desenvolvedores.
Regras de Conversão do Boolean() (Valores Falsy)
Estes 6 valores convertem para false e são chamados de valores falsy. Todo o resto é true:
<script>
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean("")); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN)); // false
</script>
Nota: Boolean("0") é true, e Boolean([]) também é true — strings não vazias e arrays não vazios são truthy.
=== Igualdade Estrita vs == Igualdade Solta
| Operador | Comportamento | Recomendação |
|---|---|---|
=== |
Retorna false se os tipos diferirem | Sempre use |
== |
Converte tipos antes de comparar | Evite |
<script>
console.log(5 === "5"); // false (tipos diferentes)
console.log(5 == "5"); // true (string convertida para número primeiro)
console.log(null === undefined); // false
console.log(null == undefined); // true
</script>
Regra de ferro: sempre use ===, nunca ==. A menos que saiba exatamente o que está fazendo (ex: value == null casa tanto null quanto undefined).
Exemplo: Comparação de Conversão de Tipos
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Conversão de Tipos</title>
<style>
body { font-family: sans-serif; padding: 20px; }
table { border-collapse: collapse; margin: 16px 0; width: 100%; max-width: 700px; }
td, th { border: 1px solid #ddd; padding: 10px 14px; text-align: left; }
th { background: #4a90d9; color: #fff; }
.surprise { color: #d9534f; font-weight: bold; }
.normal { color: #5cb85c; }
tr:nth-child(even) { background: #f9f9f9; }
</style>
</head>
<body>
<h2>Resultados de Conversão Implícita de Uma Olhada</h2>
<div id="output"></div>
<script>
const testes = [
['"5" + 3', "5" + 3, '"53"', "Concatenação de string", true],
['"5" - 3', "5" - 3, "2", "String para número", false],
['"5" * 3', "5" * 3, "15", "String para número", false],
['true + 1', true + 1, "2", "true→1", false],
['false + 1', false + 1, "1", "false→0", false],
['"" + 0', "" + 0, '"0"', "Número para string", true],
['"" == 0', "" == 0, "true", "Ambos convertem para números", true],
['"0" == false', "0" == false, "true", "Ambos convertem para 0", true],
['null == 0', null == 0, "false", "null não é igual a 0", false],
['5 === "5"', 5 === "5", "false", "Tipos diferentes", false],
];
document.getElementById("output").innerHTML = `
<table>
<tr><th>Expressão</th><th>Resultado Real</th><th>Tipo</th><th>Explicação</th><th>Contraintuitivo?</th></tr>
${testes.map(t => `<tr>
<td><code>${t[0]}</code></td>
<td class="${t[4] ? 'surprise' : 'normal'}">${t[2]}</td>
<td>${typeof t[1]}</td>
<td>${t[3]}</td>
<td>${t[4] ? "Sim" : "Não"}</td>
</tr>`).join("")}
</table>
`;
</script>
</body>
</html>
Exemplo: Referência Rápida de Valores Falsy do Boolean()
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Conversão Boolean</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; margin: 16px 0; }
.card { padding: 16px; border-radius: 8px; text-align: center; font-weight: bold; }
.falsy { background: #fff0f0; border: 2px solid #d9534f; color: #d9534f; }
.truthy { background: #f0fff0; border: 2px solid #5cb85c; color: #5cb85c; }
.card code { display: block; font-size: 18px; margin-bottom: 4px; }
.card span { font-size: 13px; opacity: 0.8; }
.note { background: #fff8e1; padding: 12px; border-radius: 6px; border-left: 4px solid #f0ad4e; margin: 16px 0; }
</style>
</head>
<body>
<h2>Resultados da Conversão Boolean()</h2>
<div id="output"></div>
<script>
const valores = [
[false, "false"],
[0, "0"],
["", '""'],
[null, "null"],
[undefined, "undefined"],
[NaN, "NaN"],
[true, "true"],
[1, "1"],
["0", '"0"'],
["false", '"false"'],
[[], "[]"],
[{}], "{}"
];
const cards = valores.map(([val, label]) => {
const resultado = Boolean(val);
const exibicao = label || String(val);
return `<div class="card ${resultado ? 'truthy' : 'falsy'}">
<code>${exibicao}</code>
<span>${resultado}</span>
</div>`;
});
document.getElementById("output").innerHTML = `
<div class="grid">${cards.join("")}</div>
<div class="note">
<code>"0"</code> é truthy! <code>[]</code> também é truthy! Apenas aqueles 7 valores falsy convertem para false.
</div>
`;
</script>
</body>
</html>
Exemplo: Cálculo com Valores de Formulário
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Cálculo com Formulário</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.calc { max-width: 400px; margin: 16px auto; padding: 20px; background: #f9f9f9; border-radius: 8px; }
.row { margin: 12px 0; }
label { display: inline-block; width: 80px; }
input { padding: 8px 12px; font-size: 16px; border: 2px solid #ccc; border-radius: 6px; width: 120px; }
button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; background: #4a90d9; color: #fff; margin-top: 8px; }
button:hover { background: #357abd; }
.result { margin-top: 16px; padding: 12px; border-radius: 6px; font-size: 18px; font-weight: bold; }
.right { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.wrong { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
</style>
</head>
<body>
<h2 style="text-align:center;">Cálculo com Formulário (Conversão de Tipos na Prática)</h2>
<div class="calc">
<div class="row">
<label>Preço:</label>
<input type="number" id="price" value="12.5" />
</div>
<div class="row">
<label>Quantidade:</label>
<input type="number" id="qty" value="3" />
</div>
<div style="text-align:center;">
<button id="calcWrong">Calcular sem conversão (errado)</button>
<button id="calcRight" style="background:#5cb85c;">Calcular com Number()</button>
</div>
<div class="result" id="result"></div>
</div>
<script>
document.getElementById("calcWrong").addEventListener("click", function() {
const preco = document.getElementById("price").value;
const qtd = document.getElementById("qty").value;
const total = preco * qtd;
document.getElementById("result").className = "result wrong";
document.getElementById("result").innerHTML =
`Sem conversão: "${preco}" * "${qtd}" = ${total}<br>` +
`(${typeof preco} * ${typeof qtd} = ${typeof total})<br>` +
`Funciona por sorte porque * converte implicitamente, mas + quebraria!`;
});
document.getElementById("calcRight").addEventListener("click", function() {
const preco = Number(document.getElementById("price").value);
const qtd = Number(document.getElementById("qty").value);
if (isNaN(preco) || isNaN(qtd)) {
document.getElementById("result").className = "result wrong";
document.getElementById("result").textContent = "Entrada inválida!";
return;
}
const total = preco * qtd;
document.getElementById("result").className = "result right";
document.getElementById("result").innerHTML =
`Com conversão explícita: ${preco} × ${qtd} = ${total.toFixed(2)}<br>` +
`(${typeof preco} × ${typeof qtd} = ${typeof total})`;
});
</script>
</body>
</html>
Exemplo: Comparação === vs ==
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Igualdade Estrita vs Solta</title>
<style>
body { font-family: sans-serif; padding: 20px; }
table { border-collapse: collapse; margin: 16px 0; width: 100%; max-width: 600px; }
td, th { border: 1px solid #ddd; padding: 10px 14px; text-align: center; }
th { background: #4a90d9; color: #fff; }
.same { background: #d4edda; }
.diff { background: #f8d7da; }
.recommend { background: #fff8e1; padding: 16px; border-radius: 8px; border-left: 4px solid #f0ad4e; margin: 16px 0; max-width: 600px; }
</style>
</head>
<body>
<h2>=== Igualdade Estrita vs == Igualdade Solta</h2>
<div id="output"></div>
<script>
const comparacoes = [
["5", 5],
[0, false],
[0, ""],
["0", false],
[null, undefined],
[null, 0],
[null, false],
[NaN, NaN],
];
const linhas = comparacoes.map(([a, b]) => {
const solta = a == b;
const estrita = a === b;
const aStr = JSON.stringify(a);
const bStr = JSON.stringify(b);
return `<tr>
<td><code>${aStr}</code> vs <code>${bStr}</code></td>
<td class="${solta ? 'same' : 'diff'}">${solta}</td>
<td class="${estrita ? 'same' : 'diff'}">${estrita}</td>
</tr>`;
});
document.getElementById("output").innerHTML = `
<table>
<tr><th>Comparação</th><th>Resultado ==</th><th>Resultado ===</th></tr>
${linhas.join("")}
</table>
<div class="recommend">
<strong>Regra de ferro</strong>: Sempre use <code>===</code>. As regras de conversão do <code>==</code> são complexas demais — exceto para o caso específico de <code>value == null</code> (que casa null e undefined), não use.
</div>
`;
</script>
</body>
</html>
❓ Perguntas Frequentes
P: Por que
"5" - 3é igual a 2 em vez de lançar um erro? R: Porque o operador-só faz operações matemáticas, então o JavaScript converte a string para número automaticamente. Apenas o operador+é ambíguo (pode ser adição ou concatenação), então ele concatena quando vê uma string. Todos os outros operadores (-,*,/,%) sempre convertem para números.
P: Por que
Number("")retorna 0 em vez de NaN? R: Essa é uma escolha de design legada. Uma string vazia é considerada como "sem número", equivalente a 0. Isso significa queNumber(input.value)retorna 0 para campos vazios em vez de NaN, o que pode enganar a lógica posterior. Useinput.value.trim() === ""para verificar valores vazios primeiro.
P: Por que
null == 0é false? R: Em comparações com==,nullsó converte de/paraundefined— ele não converte para números. Entãonull == 0é false, masnull == undefinedé true. Esse é um caso especial definido pela especificação.
📝 Atividades
- Sem executar o código, preveja os resultados destas expressões:
"10" + 5,"10" - 5,"10" * "2",true + true,Boolean("false"),"1" == 1,"1" === 1. Depois escreva código para verificar. - Escreva uma função
calcularIMC(peso, altura)onde os parâmetros vêm de inputs de formulário (strings). A função deve converter os tipos internamente antes de calcular o IMC, e tratar entradas vazias ou inválidas (retornar uma mensagem de erro). - Escreva uma função
compararEstrito(a, b)que use apenas===para comparação. Se os tipos diferirem, retorne"Tipos diferentes, não é possível comparar"diretamente; se os tipos coincidirem, retorne o resultado da comparação.



