search

JavaScript Type Conversion: Strings, Numbers, and Booleans

JavaScript type conversion refers to changing a value from one data type to another. This happens constantly in real-world code, often without you noticing. I’ve seen even experienced developers get tripped up by unexpected coercion bugs, so understanding how JavaScript handles type conversion is one of those fundamentals that pays off every time.

There are two categories: implicit conversion (where JavaScript converts values automatically) and explicit conversion (where you do it yourself using built-in functions). Both have their place, but knowing when each one fires can save you hours of debugging.

What Is Type Conversion in JavaScript?

Type conversion is the process of transforming a value from one type to another – for example, turning the string "42" into the number 42, or the number 0 into the boolean false. JavaScript is a dynamically typed language, which means variables aren’t locked to a type. That flexibility is useful, but it also means the runtime needs rules for handling mixed-type operations.

The two main categories break down like this:

TypeAlso CalledTriggered ByExample
ImplicitType coercionOperators, comparisons, conditions"5" - 2 → 3
ExplicitType castingCalling conversion functions manuallyNumber("5") → 5

String Conversion

Converting a value to a string is one of the most common operations in JavaScript. There are four main ways to do it, each with subtle differences in behavior.

String() is the safest global function – it handles null and undefined without throwing. .toString() is a method available on most values, but calling it on null or undefined will throw a TypeError. Template literals and string concatenation both trigger implicit coercion.

// Four ways to convert to string
let value = 42;

let a = String(value);          // "42" - global function, always safe
let b = value.toString();       // "42" - method on the value
let c = `${value}`;             // "42" - template literal
let d = value + '';             // "42" - concatenation with empty string

// Edge cases to watch
console.log(String(null));       // "null"
console.log(String(undefined));  // "undefined"
console.log(String([1, 2, 3])); // "1,2,3" - array becomes comma-joined string
console.log(String({}));         // "[object Object]"

// .toString() throws on null/undefined
// null.toString(); // TypeError: Cannot read properties of null

For a deeper look at working with text in JavaScript, the guide on Mastering JavaScript Strings covers string methods and patterns in detail.

When converting unknown or potentially null values to strings, always prefer String(value) over value.toString(). The global function handles null and undefined gracefully; the method does not.

Number Conversion

Converting values to numbers is just as common, especially when handling form input, URL parameters, or API responses – all of which arrive as strings.

Number() attempts a full parse of the entire string. parseInt() and parseFloat() read from left to right and stop at the first non-numeric character. The unary plus operator (+value) is shorthand for Number() and is widely used in terse code.

// Number conversion methods
console.log(Number("123"));        // 123
console.log(Number("12.5"));       // 12.5
console.log(Number(""));           // 0
console.log(Number("  42  "));     // 42 - trims whitespace
console.log(Number("42abc"));      // NaN - can't parse the full string
console.log(Number(true));         // 1
console.log(Number(false));        // 0
console.log(Number(null));         // 0
console.log(Number(undefined));    // NaN

// parseInt stops at first non-numeric character
console.log(parseInt("42abc"));    // 42 - partial parse
console.log(parseInt("0xFF", 16)); // 255 - hex parsing

// parseFloat for decimal strings
console.log(parseFloat("3.14"));   // 3.14

// Unary plus - shorthand for Number()
let str = "99";
console.log(+str);                 // 99

NaN (Not a Number) is the result you get when a numeric conversion fails. It’s a number type value – paradoxically – but it signals that a meaningful number couldn’t be produced. Always check for it with Number.isNaN() rather than the global isNaN(), which coerces its argument first and can produce false positives.

let result = Number("hello"); // NaN

// Wrong way - isNaN() coerces before checking
console.log(isNaN("hello"));        // true (coerces "hello" → NaN first)
console.log(isNaN(undefined));      // true (coerces undefined → NaN)

// Right way - Number.isNaN() checks without coercion
console.log(Number.isNaN(result));  // true
console.log(Number.isNaN("hello")); // false - it's a string, not NaN
console.log(Number.isNaN(NaN));     // true

Boolean Conversion

Every value in JavaScript is either truthy or falsy – meaning it evaluates to true or false in a boolean context. The Boolean() function makes that explicit, and the double negation (!!) is a common shorthand for the same result.

The complete list of falsy values is short and worth memorizing:

  • false
  • 0 and -0
  • 0n (BigInt zero)
  • "" (empty string)
  • null
  • undefined
  • NaN

Everything else is truthy – including empty arrays ([]), empty objects ({}), and the string "false".

// All falsy values convert to false
console.log(Boolean(false));       // false
console.log(Boolean(0));           // false
console.log(Boolean(-0));          // false
console.log(Boolean(0n));          // false
console.log(Boolean(""));          // false
console.log(Boolean(null));        // false
console.log(Boolean(undefined));   // false
console.log(Boolean(NaN));         // false

// Everything else is truthy
console.log(Boolean("false"));     // true - non-empty string
console.log(Boolean([]));          // true - empty array
console.log(Boolean({}));          // true - empty object
console.log(Boolean(-1));          // true - any non-zero number

// Double negation shorthand
let value = "hello";
console.log(!!value);              // true
console.log(!!0);                  // false

Type Coercion in Comparisons

Where type coercion causes the most confusion is in comparison operators. The == operator (loose equality) converts operands to a common type before comparing. The === operator (strict equality) does not convert – both value and type must match.

// Loose equality (==) - coerces before comparing
console.log(5 == "5");        // true - string "5" converts to number 5
console.log(0 == false);      // true - false converts to 0
console.log(null == undefined); // true - special rule
console.log(null == 0);       // false - null only equals undefined with ==
console.log("" == false);     // true - both convert to 0

// Strict equality (===) - no conversion, both must match
console.log(5 === "5");       // false - different types
console.log(0 === false);     // false - different types
console.log(null === undefined); // false - different types

// Relational operators also coerce
console.log("10" > "9");      // false - string comparison (lexicographic)
console.log(10 > "9");        // true - "9" converts to number 9
Always use === over == unless you have a specific reason to allow type coercion. Loose equality has enough edge cases to make code unpredictable.

Common Pitfalls

A few coercion behaviors come up repeatedly and trip people up even after they’ve been working with JavaScript for a while. Understanding JavaScript variables and how values are stored helps explain why some of these happen.

// null converts to 0 in arithmetic
console.log(null + 1);        // 1  (null → 0)
console.log(null * 5);        // 0

// undefined does not convert to a number
console.log(undefined + 1);   // NaN
console.log(undefined * 5);   // NaN

// + is both addition and concatenation
console.log("5" + 2);         // "52" - string wins with +
console.log("5" - 2);         // 3   - subtraction always converts to number
console.log("5" * "2");       // 10  - multiplication converts both

// Arrays and objects with +
console.log([] + []);          // "" - both arrays convert to empty strings
console.log({} + []);          // "[object Object]" when {} is an expression
console.log([] + {});          // "[object Object]"

// parseInt with leading zeros (legacy behavior)
console.log(parseInt("08"));   // 8  - fine in modern JS (ES5+)
console.log(parseInt("08", 10)); // 8 - explicit base 10, always safe

The + operator has a unique rule: if either operand is a string, it performs string concatenation. Every other arithmetic operator (-, *, /, %) converts both sides to numbers first. This asymmetry is the source of the classic "5" + 2 = "52" vs "5" - 2 = 3 surprise.

Using console.log() to inspect conversion results while debugging is covered thoroughly in Mastering JavaScript console.log().

FAQs

Common questions about JavaScript type conversion:

What is the difference between implicit and explicit type conversion in JavaScript?
Implicit type conversion (also called type coercion) happens automatically when JavaScript evaluates an expression involving mismatched types - for example, "5" - 2 silently converts the string to a number. Explicit type conversion is when you do it yourself using functions like Number(), String(), or Boolean(). Explicit conversion is generally safer because the intent is clear and the behavior is predictable.
How do I convert a string to a number in JavaScript?
The most reliable way is the Number() function: Number("42") returns 42. You can also use parseInt() or parseFloat() for partial parsing, or the unary plus operator (+"42"). If the string can't be converted to a valid number, you'll get NaN. Always check the result with Number.isNaN() when the input is uncertain.
What are falsy values in JavaScript?
Falsy values are the seven values that evaluate to false in a boolean context: false, 0, -0, 0n (BigInt zero), "" (empty string), null, undefined, and NaN. Every other value is truthy - including [], {}, and even the string "false". Use Boolean(value) or !!value to check a value's boolean interpretation.
Why does "5" + 2 return "52" instead of 7?
The + operator in JavaScript serves double duty: it handles both addition and string concatenation. When one of the operands is a string, JavaScript treats + as concatenation and converts the other operand to a string. So "5" + 2 converts 2 to "2" and joins them to get "52". By contrast, -, *, and / have no string version, so they always convert both sides to numbers - which is why "5" - 2 returns 3.
Should I use == or === in JavaScript?
Use === (strict equality) by default. It compares both value and type without coercion, so the result is always predictable. The == (loose equality) operator coerces types before comparing, which produces surprising results like 0 == false being true or "" == false being true. The only common exception where == is intentionally used is the value == null pattern, which catches both null and undefined in one check.
What does NaN mean and how do I check for it?
NaN stands for "Not a Number" and is the result of a failed numeric operation - for example, Number("hello") or 0 / 0. Despite its name, typeof NaN returns "number". To check for it, use Number.isNaN(value), not the global isNaN() function. The global version coerces its argument to a number first, which means isNaN("hello") returns true even though "hello" is a string, not NaN. Number.isNaN() only returns true for the actual NaN value.
Can I convert an object to a string in JavaScript?
Yes, but the result depends on how you do it. Calling String(obj) or obj.toString() on a plain object returns "[object Object]", which is rarely useful. For a readable representation, use JSON.stringify(obj), which converts the object to a JSON string. Arrays convert to a comma-separated list of their elements when passed to String(). If you need custom string output, define a toString() method on your object to control what gets returned.

Summary

Type conversion is baked into how JavaScript works, so fluency with it matters more than most developers expect. I find that most coercion bugs come down to a handful of repeated mistakes – leaning on == instead of ===, forgetting that + is also concatenation, or not accounting for NaN propagation in arithmetic chains.

A few rules that hold up in practice:

  • Use explicit conversion (Number(), String(), Boolean()) whenever the type of a value is uncertain.
  • Always prefer === over == unless you specifically want coercion.
  • Know the seven falsy values – they come up in conditionals constantly.
  • Use typeof to check a value’s type at runtime, and Number.isNaN() to detect failed number conversions.
  • Treat + with mixed operands carefully – when in doubt, convert explicitly before operating.

For a broader understanding of how JavaScript manages state and mutability, the guide on JavaScript Object Methods and this covers how objects interact with the type system in more advanced contexts.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo