Type Coercion and Type Conversion
JavaScript automatically converts types in certain situations (coercion) and allows explicit conversion. Understanding both is crucial for writing reliable code.
Type Coercion
Type coercion is automatic type conversion by JavaScript.
String Coercion
When using the + operator with a string:
console.log("5" + 3); // "53" (number converted to string)
console.log(3 + "5"); // "35"
console.log("Hello" + true); // "Hellotrue"
console.log("5" + null); // "5null"
console.log("5" + undefined); // "5undefined"
Numeric Coercion
With arithmetic operators (except +):
console.log("5" - 3); // 2 (string converted to number)
console.log("5" * 2); // 10
console.log("10" / 2); // 5
console.log("5" % 2); // 1
Boolean Coercion
In conditional contexts:
if ("text") {
console.log("truthy"); // Runs
}
if (0) {
console.log("never runs"); // Doesn't run
}
if ([]) {
console.log("arrays are truthy"); // Runs
}
Comparison Coercion
With loose equality (==):
console.log(5 == "5"); // true (string converted to number)
console.log(0 == false); // true
console.log(null == undefined); // true
console.log("" == false); // true
console.log([] == false); // true
Falsy and Truthy Values
Falsy Values
Only 6 values are falsy:
console.log(Boolean(false)); // 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
Truthy Values
Everything else is truthy:
console.log(Boolean(true)); // true
console.log(Boolean(1)); // true
console.log(Boolean("text")); // true
console.log(Boolean([])); // true (even empty!)
console.log(Boolean({})); // true (even empty!)
console.log(Boolean(function(){})); // true
Explicit Type Conversion
Convert types explicitly for clarity and control.
String Conversion
// Using String()
console.log(String(123)); // "123"
console.log(String(true)); // "true"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
// Using toString()
console.log((123).toString()); // "123"
console.log(true.toString()); // "true"
// Using template literals
console.log(`${123}`); // "123"
// Using concatenation
console.log("" + 123); // "123"
Number Conversion
// Using Number()
console.log(Number("123")); // 123
console.log(Number("12.5")); // 12.5
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(Number("")); // 0
console.log(Number("abc")); // NaN
// Using parseInt()
console.log(parseInt("123")); // 123
console.log(parseInt("123.45")); // 123
console.log(parseInt("0xFF")); // 255 (hexadecimal)
console.log(parseInt("123", 10)); // 123 (specify radix)
// Using parseFloat()
console.log(parseFloat("123.45")); // 123.45
console.log(parseFloat("123")); // 123
// Using unary +
console.log(+"123"); // 123
console.log(+true); // 1
console.log(+false); // 0
Boolean Conversion
// Using Boolean()
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("text")); // true
console.log(Boolean("")); // false
// Using double negation
console.log(!!1); // true
console.log(!!0); // false
console.log(!![]); // true
console.log(!!{}); // true
Practical Examples
Form Input Validation
function processAge(input) {
const age = Number(input);
if (isNaN(age)) {
return "Invalid age";
}
if (age < 0 || age > 150) {
return "Age out of range";
}
return `Valid age: ${age}`;
}
console.log(processAge("25")); // "Valid age: 25"
console.log(processAge("abc")); // "Invalid age"
console.log(processAge("-5")); // "Age out of range"
Parsing Query Parameters
function parseQueryParam(value) {
// Try to parse as number
if (!isNaN(value) && value !== "") {
return Number(value);
}
// Try to parse as boolean
if (value === "true") return true;
if (value === "false") return false;
// Return as string
return value;
}
console.log(parseQueryParam("123")); // 123
console.log(parseQueryParam("true")); // true
console.log(parseQueryParam("hello")); // "hello"
Conditional Logic
function processValue(value) {
// Explicit conversion for clarity
const isValid = Boolean(value);
const asNumber = Number(value);
const asString = String(value);
if (isValid) {
console.log(`Number: ${asNumber}, String: ${asString}`);
}
}
processValue(42); // "Number: 42, String: 42"
processValue(""); // (nothing - falsy)
Array to String
const numbers = [1, 2, 3, 4, 5];
// Implicit coercion
console.log("Numbers: " + numbers); // "Numbers: 1,2,3,4,5"
// Explicit conversion
console.log("Numbers: " + numbers.toString()); // "Numbers: 1,2,3,4,5"
console.log("Numbers: " + numbers.join(", ")); // "Numbers: 1, 2, 3, 4, 5"
Avoiding Coercion Bugs
Use Strict Equality
// Bad - loose equality with coercion
if (value == 0) { }
if (value == false) { }
if (value == "") { }
// Good - strict equality
if (value === 0) { }
if (value === false) { }
if (value === "") { }
Explicit Conversion
// Bad - relying on coercion
const age = userInput; // Could be string
if (age > 18) { } // Might coerce unexpectedly
// Good - explicit conversion
const age = Number(userInput);
if (age > 18) { }
Check for NaN
// Bad - NaN == NaN is false
const num = Number("abc");
if (num == NaN) { } // Never true
// Good - use isNaN()
const num = Number("abc");
if (isNaN(num)) { }
// Better - use Number.isNaN()
if (Number.isNaN(num)) { }
Coercion Table
| Value | String | Number | Boolean |
|---|---|---|---|
true |
“true” | 1 | true |
false |
“false” | 0 | false |
1 |
“1” | 1 | true |
0 |
“0” | 0 | false |
"1" |
“1” | 1 | true |
"0" |
“0” | 0 | true |
"" |
"" | 0 | false |
"text" |
“text” | NaN | true |
null |
“null” | 0 | false |
undefined |
“undefined” | NaN | false |
[] |
"" | 0 | true |
{} |
“[object Object]” | NaN | true |
Best Practices
Be Explicit
// Good - clear intent
const count = Number(userInput);
const isActive = Boolean(status);
const message = String(value);
// Avoid - implicit coercion
const count = userInput * 1;
const isActive = !!status;
const message = value + "";
Use Appropriate Methods
// For integers
const int = parseInt("123", 10);
// For decimals
const float = parseFloat("123.45");
// For any number
const num = Number("123");
Validate Input
function processNumber(input) {
const num = Number(input);
if (isNaN(num)) {
throw new Error("Invalid number");
}
return num;
}
Summary
- Coercion: automatic type conversion by JavaScript
- Falsy: false, 0, “”, null, undefined, NaN
- Truthy: everything else
- String conversion: String(), toString(), template literals
- Number conversion: Number(), parseInt(), parseFloat(), unary +
- Boolean conversion: Boolean(), double negation (!!)
- Best practice: use strict equality (===) and explicit conversion
Related Resources
Official Documentation
Next Steps
- JavaScript Data Types Fundamentals
- Conditional Statements in JavaScript
- Error Handling in JavaScript
Comments