Values, types, and the equality trap
typeof, truthy and falsy, and the one comparison operator to stop reaching for.
After this lesson you can
- Name JavaScript's primitive types and tell them from objects
- Predict whether a value is truthy or falsy without running it
- Explain why === is the default and when == still surprises people
JavaScript has seven primitive types: string, number, boolean,
undefined, null, symbol, and bigint. Everything else — arrays,
functions, dates, plain objects — is an object. There is exactly one
numeric type; 1 and 1.5 are both a number.
typeof "hi"; // "string"
typeof 42; // "number"
typeof undefined; // "undefined"
typeof null; // "object" — a 25-year-old bug nobody can fix now
typeof []; // "object"
typeof (() => {}); // "function"
typeof null returning "object" is not a design choice; it is a bug
from JavaScript's first implementation that shipped before anyone could
fix it without breaking the web. Comparing value === null directly is
the reliable way to ask.
Truthy and falsy
Every value is truthy in a boolean context except a short, fixed list:
false, 0, -0, "", null, undefined, and NaN. Everything
else — including "0", [], and {} — is truthy.
if ("0") console.log("truthy"); // runs: a non-empty string
if ([]) console.log("truthy"); // runs: an object, always truthy
Try it
export function falsyOnly() { const values = [0, 1, "", "a", null, "0", [], {}, false, true]; return values.filter((v) => !v);}== against ===
== compares after converting both sides to a common type. ===
compares without converting anything. The conversion rules for == are
a genuine, memorised list of special cases:
0 == "0"; // true — the string converts to a number
0 == ""; // true — empty string converts to 0
0 == false; // true — false converts to 0
null == undefined; // true — the one pair == treats as equal to each other
null == 0; // false — null converts to nothing else, not even 0
"" == "0"; // false — neither side is a number here, plain string compare
Nobody has that table memorised reliably, which is why the convention is:
use === and !== everywhere, and reach for == only for the one
legitimate case — value == null, which is true for both null and
undefined and nothing else.
NaN is never equal to anything, including itself
NaN === NaN; // false
Number.isNaN(NaN); // true — the only reliable check
isNaN(x) (the global, not Number.isNaN) first converts x to a
number, so isNaN("hello") is also true. Use Number.isNaN, which
never converts its argument.
Try it yourself
2 visible tests · 2 hidden testsImplement firstTruthy(values) that returns the first truthy value in
the array, or null if every value is falsy. Do not convert the value —
return it exactly as it was given.
firstTruthy([0,"",null,5,"a"])firstTruthy([0,"",null,false])
Sign up to check the hidden tests and save your progress. Sign up