Skip to main content
โšก Calmops

Type Coercion and Type Conversion

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

Official Documentation

Next Steps

  1. JavaScript Data Types Fundamentals
  2. Conditional Statements in JavaScript
  3. Error Handling in JavaScript

Comments