JavaScript Type Coercion Explained: Why '1' + 1 = '11' Makes Sense

JavaScript Type Coercion Explained: Why '1' + 1 = '11' Makes Sense

In JavaScript:

'1' + 1    // '11' (string)
'1' - 1    // 0 (number)

Same operands, different operators, different results. This is type coercion—JavaScript automatically converting values between types.

The + Operator Prefers Strings

When + sees a string, it converts everything to strings and concatenates:

'1' + 1       // '11'
'1' + true    // '1true'
'1' + null    // '1null'
'1' + undefined  // '1undefined'

The logic: + works for both addition and concatenation. If either operand is a string, assume concatenation.

Other Operators Prefer Numbers

Subtraction, multiplication, and division have no string equivalent. They convert to numbers:

'5' - 2       // 3
'10' * '2'    // 20
'12' / '4'    // 3
'5' - true    // 4 (true becomes 1)
'5' - 'abc'   // NaN (can't convert 'abc')

How Values Convert to Numbers

JavaScript's Number() function shows the conversion rules:

Number('123')      // 123
Number('12.5')     // 12.5
Number('')         // 0
Number(' ')        // 0
Number('abc')      // NaN
Number(true)       // 1
Number(false)      // 0
Number(null)       // 0
Number(undefined)  // NaN

Empty strings and whitespace become 0. Non-numeric strings become NaN.

How Values Convert to Strings

The String() function shows string conversion:

String(123)        // '123'
String(true)       // 'true'
String(false)      // 'false'
String(null)       // 'null'
String(undefined)  // 'undefined'
String({})         // '[object Object]'
String([1, 2])     // '1,2'

Everything has a string representation, though it's not always useful.

The Double Equals Trap

Loose equality (==) coerces types before comparing:

1 == '1'           // true (string '1' becomes number 1)
0 == false         // true (false becomes 0)
'' == 0            // true (empty string becomes 0)
null == undefined  // true (special rule)

This causes confusion. Use strict equality (===) instead:

1 === '1'          // false (different types)
0 === false        // false
'' === 0           // false
null === undefined // false

Strict equality doesn't coerce. Same type and value required.

Truthy and Falsy Values

In boolean contexts, values coerce to true or false:

if (value) { }  // Coerces value to boolean

Falsy values (coerce to false):

  • false
  • 0
  • '' (empty string)
  • null
  • undefined
  • NaN

Everything else is truthy, including:

if ('0') { }       // true (non-empty string)
if ('false') { }   // true (non-empty string)
if ([]) { }        // true (empty array is truthy)
if ({}) { }        // true (empty object is truthy)

Array to Number Coercion

Arrays have surprising coercion behavior:

[] + []           // '' (two empty strings)
[] + {}           // '[object Object]'
{} + []           // 0 (confusing - {} is block, not object)
[1] + [2]         // '12' (arrays become strings)
[1, 2] + [3]      // '1,23'

Arrays convert to strings (via join(',')), then concatenate or convert to numbers.

Object to Primitive Coercion

Objects convert via valueOf() or toString():

const obj = {
    valueOf() { return 42; },
    toString() { return 'hello'; }
};

obj + 1           // 43 (uses valueOf)
String(obj)       // 'hello' (uses toString)

The operator determines which method is called.

The Unary + Trick

Unary + converts to number:

+'123'            // 123
+'12.5'           // 12.5
+true             // 1
+false            // 0
+null             // 0
+undefined        // NaN

This is shorthand for Number(). Common in code golf and minification.

Explicit vs Implicit Coercion

Explicit: You call conversion functions:

Number('123')     // Explicit
String(123)       // Explicit
Boolean(1)        // Explicit

Implicit: JavaScript converts automatically:

'1' + 1           // Implicit
'5' - 2           // Implicit
if (value) { }    // Implicit

Explicit is clearer. Implicit is shorter but can surprise.

Avoiding Coercion Bugs

Use strict equality:

if (x === 5) { }  // Not if (x == 5)

Convert explicitly when needed:

const num = Number(input);
const str = String(value);

Check types before operations:

if (typeof x === 'number' && typeof y === 'number') {
    return x + y;
}

Use parseInt/parseFloat for strings:

parseInt('123px')     // 123 (stops at non-digit)
Number('123px')       // NaN

When Coercion Is Useful

Converting user input:

const age = +prompt('Enter age:');  // Converts string to number

Boolean checks:

if (array.length) { }  // Truthy if array has items
if (object.property) { }  // Truthy if property exists and isn't falsy

Default values:

const value = input || 'default';  // If input is falsy, use default

But nullish coalescing (??) is better:

const value = input ?? 'default';  // Only if null/undefined

Template Literals Always Coerce

Template literals convert everything to strings:

`Result: ${123}`         // 'Result: 123'
`Value: ${true}`         // 'Value: true'
`Object: ${{a: 1}}`      // 'Object: [object Object]'

Common Gotchas

Leading zeros in numeric strings:

parseInt('08')       // 8
parseInt('08', 10)   // 8 (always specify radix)

Array length coercion:

if (array.length) { }  // Works, but:
if (array.length > 0) { }  // More explicit

null vs undefined:

null == undefined       // true (coerced)
null === undefined      // false (strict)
null + 1               // 1 (null becomes 0)
undefined + 1          // NaN (undefined becomes NaN)

TypeScript's Role

TypeScript prevents many coercion errors at compile time:

function add(a: number, b: number) {
    return a + b;
}

add('1', 1);  // Error: Argument of type 'string' is not assignable

Further Reading

Kyle Simpson's You Don't Know JS: Types & Grammar covers coercion comprehensively.

The ECMAScript specification defines all coercion rules precisely.

MDN's guide to equality comparisons explains == vs === in detail.

Type coercion is one of JavaScript's defining features. Understanding it turns confusing behavior into predictable rules.

Wear the code

Product mockup

"1" + 1; Developer T-Shirt (JavaScript Edition — Dark Mode)

£25.00

View product
Product mockup

"1" + 1; Developer T-Shirt (JavaScript Edition — Light Mode)

£25.00

View product

0 comments

Leave a comment

Please note, comments need to be approved before they are published.