Suggest an editImprove this articleRefine the answer for “Type coercion in JavaScript (implicit vs explicit)”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Type coercion** is JavaScript converting a value from one type to another, automatically or on your command. Implicit coercion happens during operations (`"5" + 3` gives `"53"`). Explicit coercion is calling `Number()`, `String()`, or `Boolean()` yourself. ```javascript "5" + 3; // "53" - string wins with + "5" - 3; // 2 - string becomes number Number("5"); // 5 - explicit conversion ``` **Key rule:** use `===` instead of `==` to prevent coercion in comparisons.Shown above the full answer for quick recall.Answer (EN)Image**Type coercion** is JavaScript converting a value from one type to another, either automatically during an operation or explicitly when you call a conversion function yourself. ## Theory ### TL;DR - Implicit coercion happens without you asking. `"5" + 3` gives `"53"`, not `8`. - Explicit coercion is calling `Number()`, `String()`, or `Boolean()` on purpose. - The `+` operator concatenates if either operand is a string. Every other math operator converts to numbers. - `==` triggers coercion before comparing. `===` does not. - Eight values are falsy. Everything else is truthy, including `[]` and `{}`. ### Quick example ```javascript // Implicit: JavaScript decides "5" + 3; // "53" - string wins with + "5" - 3; // 2 - string becomes number true + 1; // 2 - true becomes 1 null + 5; // 5 - null becomes 0 // Explicit: you decide Number("5"); // 5 String(42); // "42" Boolean(0); // false ``` In `"5" + 3`, JavaScript sees a string and converts the number. In `"5" - 3`, subtraction has no string meaning, so the string becomes a number instead. ### Three contexts for implicit coercion JavaScript coerces values in three main situations. **String context** (the `+` operator with a string operand): the other value becomes a string. `"5" + null` gives `"5null"`. `"5" + {}` gives `"5[object Object]"`. Anything that touches `+` when a string is nearby becomes a string. **Numeric context** (`-`, `*`, `/`, `%`, unary `-`): operands become numbers. `"6" * "2"` gives `12`. `null` becomes `0`. `undefined` becomes `NaN`. `true` becomes `1`, `false` becomes `0`. **Boolean context** (conditionals, `!`, `||`, `&&`): values get evaluated as truthy or falsy. Empty string is falsy. Zero is falsy. `null`, `undefined`, and `NaN` are falsy. But `[]` and `{}` are truthy. That trips people up constantly. ### The eight falsy values | Value | Type | | --- | --- | | `false` | Boolean | | `0` | Number | | `-0` | Number | | `0n` | BigInt | | `""` | String | | `null` | null | | `undefined` | undefined | | `NaN` | Number | Everything else is truthy. `"0"`, `"false"`, `[]`, `{}` are all truthy. This shows up as a direct question in interviews and as a real bug in production. ### Explicit coercion tools `Number(value)` converts by the spec rules. `Number("")` gives `0`, `Number(null)` gives `0`, `Number(undefined)` gives `NaN`, `Number("abc")` gives `NaN`. `parseInt("42px")` pulls out `42` and stops at the first non-numeric character. `parseFloat("3.14abc")` does the same for decimals. Both are useful when parsing user input or CSS values. `String(value)` is the safe way to stringify anything. `String(null)` gives `"null"`, unlike `null.toString()` which throws a TypeError. `Boolean(value)` and the double-negation `!!` produce the same result. `!!` is just shorter inside conditions. ### Loose vs strict equality `==` applies coercion rules before comparing. `===` compares type and value together, no coercion involved. The [strict equality operator (`===`)](/questions/equality-operators-in-javascript) is the default choice for most comparisons. ```javascript "5" == 5; // true - string becomes number null == undefined; // true - special rule in the spec null == 0; // false - null only equals null or undefined "" == false; // true - both become 0 [] == false; // true - [] becomes "" becomes 0 ``` The `null == undefined` rule is there by design. They are the only two values that equal each other with `==` and nothing else. Writing `if (value == null)` catches both `null` and `undefined` in one condition, which some teams use intentionally. ### Common mistakes These appear in interviews. Often literally the same examples. ```javascript [] + []; // "" - both convert to "", concatenated [] + {}; // "[object Object]" - [] is "", {} becomes a string {} + []; // 0 - {} parsed as a block, +[] is unary plus on [] true + true; // 2 - both become 1 "2" + "2" - "2"; // 20 - "2"+"2" is "22", then "22"-"2" is 20 NaN === NaN; // false - NaN is not equal to itself typeof NaN; // "number" - it really is ``` The `{} + []` result depends on context. At the start of a console line, `{}` is a block statement, so `+[]` is unary plus on an empty array, giving `0`. Inside an expression like `var x = {} + []`, you get `"[object Object]"` instead. I once spent an hour debugging a React component that rendered `0` instead of nothing. The culprit was `count && <Component />` with `count` coming from an empty array's `.length`. [NaN](/questions/nan-in-javascript) causes similar surprises when unchecked number conversions flow through arithmetic. ### Where this appears in real code - React conditionals: `count && <Component />` renders the text `0` when `count` is `0`. Use `count > 0 && <Component />` instead. - URL params: `Number(searchParams.get("page"))` returns `0` when the param is missing. Check for `null` before converting. - API responses: backends sometimes send `"true"` as a string. `Boolean("true")` is `true`, and so is `Boolean("false")`. Compare with `=== "true"` for string booleans. - Form inputs: `input.value` is always a string. Multiplication coerces it to a number, but addition concatenates. Call `Number()` explicitly. ### Follow-up questions **Q:** Why does `typeof NaN` return `"number"`? **A:** NaN is defined in IEEE 754 as a numeric type. It represents an invalid computation result, like `0/0` or `parseInt("abc")`. JavaScript follows that spec directly. **Q:** What is the difference between `null == undefined` and `null === undefined`? **A:** `null == undefined` is `true` because the spec has a special rule for this pair. `null === undefined` is `false` because their types differ. This is one of the few cases where `==` behaves predictably. **Q:** When would you actually use `==` over `===`? **A:** The main case is `if (value == null)`, which catches both `null` and `undefined` at once. Outside of that pattern, `===` everywhere. **Q:** How does JavaScript convert an object to a primitive during coercion? **A:** It calls `valueOf()` first, then `toString()`. If neither returns a primitive, a TypeError is thrown. Arrays get their `toString()` from `join("")`, which is why `[] + []` gives `""`. **Q:** What does `[] == ![]` evaluate to, and why? **A:** `true`. `![]` is `false` because `[]` is truthy. Then `[] == false` coerces both sides: `[]` becomes `""`, `""` becomes `0`, `false` becomes `0`. So `0 == 0` is `true`. This is exactly why senior devs avoid `==` in most contexts. ## Examples ### Explicit conversion in form handling ```javascript function calculateTotal(priceInput, quantityInput) { const price = Number(priceInput.value); const quantity = Number(quantityInput.value); if (isNaN(price) || isNaN(quantity)) { return "Invalid input"; } return price * quantity; } // priceInput.value = "10", quantityInput.value = "3" // "10" * "3" = 30 - works via implicit coercion anyway // "10" + "3" = "103" - but + would concatenate, not add ``` `input.value` is always a string. Multiplication happens to coerce strings to numbers, so the implicit path produces the right number. But one accidental `+` and you get concatenation. Explicit `Number()` makes the intent clear and surfaces `NaN` before it propagates into a price total. ### The `+` operator trap in React ```javascript function CartSummary({ items }) { const count = items.length; return ( <div> {/* Bug: renders "0" as text when count is 0 */} {count && <p>Items in cart: {count}</p>} {/* Fix: convert to boolean first */} {count > 0 && <p>Items in cart: {count}</p>} {/* Or use a ternary */} {count ? <p>Items in cart: {count}</p> : null} </div> ); } ``` When `count` is `0`, the expression `0 && <p>...</p>` short-circuits to `0`, and React renders the number `0` in the DOM. This is a real bug that shows up in code review regularly. `count > 0` evaluates to a boolean before the `&&`, so React gets `false` and renders nothing. ### Handling coercion in API responses ```javascript async function getUser(id) { const response = await fetch(`/api/users/${id}`); const data = await response.json(); // API returns: { active: "true", score: "42", role: null } return { id: data.id, active: data.active === "true", // not Boolean("true") score: Number(data.score) || 0, // 0 as fallback for NaN role: data.role ?? "guest", // ?? not ||, to allow 0 and "" }; } ``` `Boolean("false")` is `true` because any non-empty string is truthy. For string booleans from an API, compare with `=== "true"` directly. The `??` operator only triggers on `null` and `undefined`, not on `0` or `""`, making it safer than `||` for numeric defaults.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.