Interview reference for the JS standard-library APIs that get reached for constantly โ the exact gotchas that cost time mid-interview, not a full language guide.
const m = new Map<string, number>();
m.set('a', 1); m.get('a'); m.has('a'); m.delete('a');
m.size; // PROPERTY, no ()
for (const [k, v] of m) {}
const s = new Set<number>();
s.add(5); s.has(5); s.delete(5);
s.size; // PROPERTY, no ()
for (const v of s) {}
[...s]; // to array
new Set([1, 2, 3]); // โ
needs an ARRAY
new Set(1, 2, 3); // โ TypeError
.keys() / .values() / .entries() Give an ITERATOR, Not an Array โ on Map, Set AND Array.keys() | .values() | .entries() | |
|---|---|---|---|
| Map | keys | values | [key, value] |
| Set | same as values | values | [v, v] |
| Array | indexes | values | [index, value] |
m.keys().sort((a, b) => a - b); // โ iterator has no .sort()
[...m.keys()].sort((a, b) => a - b); // โ
spread first
Array.from(m.values()); // โ
same idea
Object.entries(obj); // โ ๏ธ plain object: a function, returns a real ARRAY
.sort(), .map() or .filter() on an iterator. A bare Set is the same: iterable, not an array. And .sort() with no comparator sorts as STRINGS (10 before 2) โ pass (a, b) => a - b.[...x] or Array.from(x) BEFORE any array method. Only Object.keys/values/entries(obj) hands back an array.const pq = new MinPriorityQueue<number>(); // simple numeric
const pq = new MinPriorityQueue<number[]>(x => x[0]); // callback extracts comparison key
const pq = new MaxPriorityQueue<number[]>(x => x[0]); // reverse order, same API
pq.enqueue(item); // O(log n)
pq.dequeue(); // O(log n), returns the element directly
pq.front(); // O(1) peek
pq.isEmpty(); // O(1)
pq.size(); // METHOD here โ needs ()
dequeue()/front() return the element directly โ e.g. const [dist, node] = pq.dequeue().Math.max(1, 5, 3); // โ
individual args โ 5
Math.max([1, 5, 3]); // โ NaN
Math.max(...[1, 5, 3]); // โ
spread the array
Math.max(...hugeArr); // โ RangeError around 100k+ items (engine-dependent) โ use a loop
.size/.length = properties (no parens). PQ's .size() = method (needs parens) โ the one exception to watch for. Math.max/min never take an array directly โ always spread it..get()/.set() ONLY โ Never Bracket Notationconst m = new Map<string, number>();
m.set('a', 1);
m.get('a'); // โ
1
m['a']; // โ undefined โ does NOT read from the Map's data
m['a'] = 5; // โ sets a regular object PROPERTY named "a", not a Map entry
map[key] silently does NOT throw and does NOT touch the Map's actual key-value data โ always use .get(key) / .set(key, val) / .has(key), never bracket notation, on a Map.Number Is Exact Only Up to 15 Digits โ Beyond That, BigIntNumber.MAX_SAFE_INTEGER; // 9007199254740991 = 2^53 โ 1 โ 16 digits
Number("12345678901234567890"); // โ 12345678901234567000 โ silently wrong, no error
BigInt("12345678901234567890") + 1n; // โ
exact at any length
BigInt(a) + BigInt(b) === BigInt(c); // โ
LC 306 Additive Number check
โ
When to reach for BigInt:
9 ร 10^15BigInt.1n + 2 โ TypeError (can't mix BigInt and Number โ write 1n + 2n) ยท 7n / 2n โ 3n (drops the fraction) ยท Math.max(1n, 2n) โ TypeError (Math.* doesn't take BigInt) ยท BigInt(1.5) โ RangeError ยท 1n / 0n โ RangeError ยท JSON.stringify(1n) โ TypeError.๐ ๏ธ Using it:
const nums = strs.map(s => BigInt(s)); // convert once, up front
arr.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)); // โ a - b throws TypeError
new Map<bigint, number>(); // keys match by value โ
x.toString(); // return huge answers as strings
BigInt.asIntN(64, x); // imitate a 64-bit long
"Without BigInt?" โ add the two strings digit by digit from the right, carrying 1 (LC 415).
Number is fine. 16+ digits โ BigInt (or string addition if BigInt isn't allowed). Never mix n numbers with plain numbers.new Array(n).fill([]) โ Every Row Is the SAME Arrayconst g = new Array(3).fill([]);
g[0].push(1); // โ [[1],[1],[1]] โ one array shared by all rows
const g = Array.from({length: 3}, () => []); // โ
a fresh array per row
.fill(x) copies the REFERENCE. fill(0) is fine (numbers), fill([]) / fill({}) is not. 2D DP: Array.from({length: m}, () => new Array(n).fill(0)).const seen = new Set<number[]>();
seen.add([0, 1]);
seen.has([0, 1]); // โ false โ a different array object
const seen = new Set<string>();
seen.add(`${r},${c}`);
seen.has(`${r},${c}`); // โ
true โ strings compare by value
`${r},${c}`, or the number r * cols + c (faster). Same rule for Map keys.s[i] = 'x' Does Nothings[0] = 'z'; // โ silently ignored (TypeError in strict mode)
const a = s.split(''); a[0] = 'z'; a.join(''); // โ
edit as an array, join back
s.charCodeAt(i) - 97; // letter โ index ('a' = 0 โฆ 'z' = 25)
String.fromCharCode(97 + k); // index โ letter
split('') โ edit โ join(''). Building one piece by piece? Push to an array, join once at the end.% and / With Negatives, and 32-bit Bit Ops-1 % 5; // โ -1, not 4 โ % keeps the sign of the LEFT side
((x % n) + n) % n; // โ
always 0โฆn-1 (circular index, hashing)
Math.floor(-7 / 2); // -4 โ rounds down
Math.trunc(-7 / 2); // -3 โ cuts the decimal (what Java/C++ `/` does)
1 << 31; // -2147483648 โ bit ops work on 32-bit signed ints
a / b is a float โ wrap it: Math.floor for positives, pick floor vs trunc on purpose for negatives. | & ^ << >> cut numbers to 32 bits: fine up to 2^31, wrong beyond it.queue.shift() Is Slow on Big Arrays โ BFS With a Head Pointerwhile (q.length) { const x = q.shift(); } // โ each shift moves every element โ O(n)
let head = 0;
while (head < q.length) { const x = q[head++]; } // โ
O(1) per pop, push() still works
shift() calls took ~3.5 s, the head pointer ~1 ms. Use q[head++] for BFS queues.const o: any = {}, m = new Map()
o[1] = 'a'; o['1'] = 'b' // 1 key: both become "1"
m.set(1, 'a'); m.set('1', 'b') // 2 keys: types kept
count['constructor'] = (count['constructor'] || 0) + 1 // โ starts from a function, not 0
๐ Order: a Map is strictly insertion order. An Object puts integer-like keys first, sorted: keys b, a, 2, 1 come out as 1, 2, b, a. (Map access is #6.)
constructor, toString). Map keeps types and insertion order. For counting, or any key you don't control, use Map.function isAlphaNumeric(ch: string) {
const c = ch.toLowerCase();
return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
}
// shorter: /[a-z0-9]/i.test(ch)