Predictable code in a flexible language
Type questions test whether you know when JavaScript converts values for you. The professional answer is always the same: convert explicitly and compare strictly.
- TypesPrimitives, objects and typeof.
- CoercionTruthy/falsy, + vs -, == rules.
- NumbersNaN, floating point and BigInt.
JavaScript's type system is flexible — sometimes too flexible. Interviewers ask about types and coercion because they cause real bugs: form values that are strings, sums that concatenate, comparisons that surprise. Know the rules and you can predict any of these questions.
1. What are the data types in JavaScript?
Seven primitives — string, number, bigint, boolean, undefined, null and symbol — plus objects (including arrays, functions, dates, maps). Primitives are immutable and compared by value; objects are compared by reference.
console.log({} === {}); // false — two different objects
const a = { n: 1 };
const b = a;
b.n = 2;
console.log(a.n); // 2 — same object2. What does typeof return for each type? What are its quirks?
It returns a string: "string", "number", "bigint", "boolean", "undefined", "symbol", "function" or "object". Quirks: typeof null is "object" (a historic bug) and arrays are "object" too — use Array.isArray().
typeof null; // 'object'
typeof []; // 'object'
Array.isArray([]); // true
typeof function () {}; // 'function'
typeof NaN; // 'number'3. Which values are falsy?
Exactly these: false, 0, -0, 0n, "", null, undefined and NaN. Everything else is truthy — including "0", "false", [] and {}.
if ([]) console.log('empty array is truthy');
const qty = 0;
console.log(qty || 10); // 10 — || treats 0 as missing
console.log(qty ?? 10); // 0 — ?? only replaces null/undefined4. Explain implicit type coercion with examples.
JavaScript converts types automatically in some operations. + with a string concatenates; other arithmetic operators convert to numbers; == converts before comparing. Convert explicitly with Number(), String() and Boolean() to avoid surprises — especially with form inputs, which are always strings.
'5' + 3; // '53'
'5' - 3; // 2
'5' * '2'; // 10
[] + {}; // '[object Object]'
true + 1; // 2
Number('12px'); // NaN
parseInt('12px', 10); // 125. How does == compare values?
Loose equality converts types first: null == undefined is true (and they equal nothing else), booleans become numbers, strings become numbers when compared with numbers, and objects are converted to primitives. That produces results like "" == 0 and "0" == false being true. Use ===.
0 == ''; // true
'0' == false; // true
null == undefined; // true
null == 0; // false
NaN == NaN; // false6. What is NaN and how do you check for it?
NaN (“not a number”) is the result of invalid number operations. It is the only value not equal to itself. Use Number.isNaN(x); the global isNaN() converts first, so isNaN("hello") is true, which is misleading.
const n = Number('abc');
n === NaN; // false — never works
Number.isNaN(n); // true
isNaN('hello'); // true (converted first)
Number.isNaN('hello'); // false7. Why is 0.1 + 0.2 not 0.3? How do you handle money?
Numbers are 64-bit floating point, which cannot represent 0.1 exactly, so tiny errors appear. For money, store amounts in the smallest unit (paise) as integers, or use a decimal library; for display, format with Intl.NumberFormat.
0.1 + 0.2; // 0.30000000000000004
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true
const totalPaise = 1999 + 2501; // work in integers
new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR' }).format(totalPaise / 100);
// '₹45.00'8. When would you use BigInt and Symbol?
BigInt holds integers beyond Number.MAX_SAFE_INTEGER (2⁵³−1) exactly — large IDs, cryptography, precise counters. You cannot mix it with numbers without converting. Symbol creates a unique key that cannot clash with other properties — used for hidden metadata and well-known hooks such as Symbol.iterator.
const big = 9007199254740993n;
console.log(big + 2n); // 9007199254740995n
// big + 1 -> TypeError: cannot mix BigInt and other types
const id = Symbol('id');
const user = { name: 'Asha', [id]: 42 };
console.log(Object.keys(user)); // ['name'] — symbol keys are hiddenRemember
Key points
- Eight falsy values
Everything else, even [] and "0", is truthy.
- + concatenates with strings
Other operators convert to numbers.
- Number.isNaN
Not the global isNaN.
- Money in integers
Avoid floating-point errors.
Interview drill
Follow-up questions
What the interviewer asks after your first answer. Turn on practice mode, answer each one aloud, then reveal.
-
1 What is the difference between null and undefined? Basic
undefinedmeans a value was never assigned;nullis an intentional empty value set by the programmer. -
2 How do you safely check that a value is a number? Basic
typeof x === "number" && Number.isFinite(x)— excludes NaN and Infinity. -
3 What does Object.is do differently from ===? Intermediate
Object.is(NaN, NaN)is true andObject.is(0, -0)is false; otherwise it matches===. -
4 What is the result of [] == ![]? Advanced
true:![]is false; then[] == falseconverts both to numbers —""becomes 0 and false becomes 0. -
5 How do you convert a string to a number reliably? Basic
Number(str)for whole strings (returns NaN for "12px"),parseInt(str, 10)orparseFloatto read a leading number. Always pass the radix to parseInt. -
6 Why is typeof undeclaredVariable safe but using it is not? Intermediate
typeofreturns"undefined"for undeclared names without throwing; reading the name directly throws a ReferenceError (except for let/const in the temporal dead zone, where typeof also throws).