JavaScriptNov 3, 2026 · 6 min read

coercions in js

Back in my early days of writing JavaScript, coercion bit me more times than I care to admit. Not the trivia kind you see in interview questions. The real kind, where a value quietly is not the type you thought it was and your code does the wrong thing without throwing a single error. No red text, no crash, just wrong.

The whole thing is one idea: JavaScript converts types for you, silently, whenever an operator wants a different type than the one it got. Once you know the two rules below, most of the weirdness stops being weird.

The plus sign picks a side

If either side of + is a string, JavaScript turns the other side into a string too and concatenates. Otherwise it turns both into numbers and adds. That is the entire rule, and it explains the classics:

plus-coercion.jsTypeScript
"5" + 3 // "53" (string wins, 3 becomes "3")
"5" - 3 // 2 (minus has no string mode, always numbers)
[] + [] // "" (both arrays become empty strings)
[] + {} // "[object Object]"

The famous one, + [], equals 0 for a sillier reason: at the start of a statement JavaScript reads as an empty code block, not an object, so what is left is +[], unary plus on an empty array, which coerces to 0. Wrap it in parentheses and it behaves like you expected.

== is the real trap, === is the fix

Loose equality converts both sides until they match, and the conversion table is not what you would guess:

loose-equality.jsTypeScript
"" == 0           // true
"0" == false    // true
null == undefined // true
null == 0       // false (yes, really)

The fix is boring and it works: use ===, which checks the type first and never converts anything. If the types do not match, the answer is false, full stop. I have not written == on purpose in years.

Where this bites you in real code

The trivia is fun, but here is where it actually costs you. Form inputs are always strings, so input.value + 1 concatenates instead of adding. An API sends a number back as a string and your total is suddenly "10050" instead of 150. A check like if (count) skips 0 because 0 is falsy, and an empty string is falsy too. None of these throw. They just quietly do the wrong thing, and you find out from a user, not from your console.

The habit that saves me: convert on purpose, at the boundary. Number(input.value) the second a value enters your code, and === everywhere after that. If a conversion is explicit, it cannot surprise you.

Try it live

Tap any of these and see what JavaScript actually does with it. Guess first, it is more fun that way:

Live: coercion playground
Tap an expression to see what JavaScript actually does with it.

So, what have I learnt?

  • + concatenates if either side is a string, adds if both are numbers. That one rule explains most of the classics.
  • == converts until both sides match, and the conversion table is not guessable. === never converts, so use it.
  • The bugs that cost real time are never the trivia ones. They are a string where a number should be, found by a user instead of an error.
  • Convert on purpose at the boundary (Number(), String()), and the surprises mostly disappear.
  • typeof is your friend when a value is misbehaving. Check the type before you blame the logic.