JavaScript and TypeScript interview questions

15 programming language interview questions on JavaScript and TypeScript, each with the correct answer and a full explanation.

JavaScript

What does this log?
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i));
}
Show answer

Answer

3 3 3
var is function scoped, so all three callbacks share one i, which is 3 once the loop ends. let creates a fresh binding per iteration and logs 0 1 2.

Source: MDN: Closures

What is the log order?
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
console.log(4);
Show answer

Answer

1 4 3 2
Synchronous code runs first. Promise callbacks are microtasks and run as soon as the stack is empty, before any timer task.

Source: MDN: The event loop

In JavaScript, which expression is true?
Show answer

Answer

null == undefined
Loose equality treats null and undefined as equal to each other only. NaN is not equal to itself, use Number.isNaN. Two object literals are different references.

Source: MDN: Equality comparisons and sameness

In JavaScript, what does [10, 9, 1].sort() return?
Show answer

Answer

[1, 10, 9]
Without a comparator, sort converts elements to strings and compares UTF-16 code units, so "10" comes before "9". Pass (a, b) => a - b for numbers.

Source: MDN: Array.prototype.sort()

In JavaScript, what does ['1', '2', '3'].map(parseInt) return?
Show answer

Answer

[1, NaN, NaN]
map passes (value, index), so parseInt gets radix 0, 1 and 2. Radix 0 means default, radix 1 is invalid, and 3 is not a digit in base 2. Use map(Number) or a lambda.

Source: MDN: parseInt()

What does this log?
const a = { n: { v: 1 } };
const b = { ...a };
b.n.v = 2;
console.log(a.n.v);
Show answer

Answer

2
Spread copies only the top level, so b.n is the same object as a.n. Use structuredClone for a deep copy.

Source: MDN: Spread syntax

In an ES module, what happens on the last line?
const obj = { n: 1, get() { return this.n; } };
const g = obj.get;
g();
Show answer

Answer

It throws a TypeError
this is set by how a function is called. A bare call in strict mode, which modules always use, gives this = undefined, so reading this.n throws. In sloppy scripts it would read the global object and return undefined. Fix with obj.get.bind(obj).

Source: MDN: this

What is wrong here?
items.forEach(async (item) => {
  await save(item);
});
console.log("done");
Show answer

Answer

"done" logs before the saves finish, and failures go unhandled
forEach ignores the promises its callback returns. Use for...of with await for sequential work, or await Promise.all(items.map(save)) for parallel work.

Source: MDN: Array.prototype.forEach()

In JavaScript, you fire 5 independent requests and need every result, even if some fail. Which do you await?
Show answer

Answer

Promise.allSettled
allSettled waits for all and reports each as fulfilled or rejected. all rejects on the first failure. race settles with the first to finish. any resolves with the first success.

Source: MDN: Promise.allSettled()

Three independent fetches each take about 1 second. How long does this take?
for (const url of urls) {
  results.push(await fetch(url));
}
Show answer

Answer

About 3 seconds
Each await waits before the next fetch starts, so they run one after another. Start them all first: await Promise.all(urls.map(fetch)).

Source: MDN: The event loop

In JavaScript, what does 0.1 + 0.2 === 0.3 evaluate to?
Show answer

Answer

false
JavaScript numbers are IEEE 754 doubles, and 0.1 + 0.2 is 0.30000000000000004. Compare with a tolerance, or use integers such as cents for money.

Source: MDN: Equality comparisons and sameness

What does this log?
const user = { name: "Ana" };
user.name = "Bo";
console.log(user.name);
Show answer

Answer

Bo
const stops the variable being reassigned, not the object being mutated. Object.freeze would block the change, and only at the top level.

Source: MDN: const

TypeScript

In TypeScript, const user = JSON.parse(body) as User. The body has no email field. What happens at runtime?
Show answer

Answer

Nothing is checked, user.email is just undefined
Types are erased when compiling to JavaScript, and as is only an assertion to the compiler. Validate untrusted input with a runtime check or a schema library.

Source: TypeScript handbook: Everyday types

Which assignment compiles?
interface P { x: number }
const a = { x: 1, y: 2 };
const p1: P = a;
const p2: P = { x: 1, y: 2 };
Show answer

Answer

Only p1
Typing is structural, so a with an extra y is still a P. Excess property checks apply only to fresh object literals, which is why p2 is an error.

Source: TypeScript handbook: Object types

In TypeScript, a function receives data from an untrusted source. Which parameter type forces the caller to narrow before use?
Show answer

Answer

unknown
unknown accepts anything but allows no operations until narrowed. any switches off checking. object only rules out primitives, and never accepts no value at all.

Source: TypeScript handbook: Everyday types

These questions come from the Language Gotchas pack in Bertopia.

More programming language topics

Practise these on your commute