interviewpath
  • 0day streak
  • 10total XP
  • Level 1
0/7

Unit 2 · Software engineering · Lesson 12 of 15

JavaScript and TypeScript essentials

JavaScript runs every web frontend and much tooling, and TypeScript adds a static type system that disappears at runtime. Frontend and full-stack interviews probe the semantics behind real bugs (closures, this, prototypes, equality, numbers, promise ordering) and whether you use types to model data while still validating untrusted input at runtime.
About 4 hFocus mode

Step 1: Learn the ideas

  • Scope, closures and var versus let
  • this binding rules and arrow functions
  • Prototypes and classes
  • Equality: ==, === and Object.is
  • Numbers: IEEE 754, safe integers, NaN, BigInt
  • Promises, async/await and the promise combinators
  • Structural typing and excess property checks
  • Narrowing, discriminated unions and exhaustiveness
  • unknown versus any; generics and constraints
  • Type erasure and runtime validation at boundaries

Why it matters

Many frontend bugs come from language semantics rather than frameworks: a handler that loses this, a stale closure, a 64-bit ID rounded during JSON parsing, a rejected promise nobody awaited. TypeScript prevents many of them, but only inside the compiler's view of the program: data from the network, storage or user input arrives untyped whatever the annotations claim. Interviews test both halves: predicting what the runtime does, and choosing types that make invalid states hard to represent.

Core ideas

Closures. A function keeps access to the variables in scope where it was created, not to snapshots of their values. let and const create a fresh binding per loop iteration; var is function-scoped, so callbacks created in a var loop all see the final value. Closures implement private state, memoization and debouncing, and they cause stale-value bugs when a callback holds on to an old variable.

this. For ordinary functions the call decides this: obj.f() binds obj; a plain call f() gets undefined in strict code (modules and class bodies are strict); new binds the newly created object; call, apply and bind set it explicitly. Arrow functions have no this of their own and use the enclosing one. Passing obj.method as a callback detaches it from obj.

Prototypes. Property lookup walks the prototype chain until it finds the key or reaches null. class syntax builds the same structure: methods live on Class.prototype and are shared by all instances, with stricter rules such as requiring new.

Equality and numbers. === compares without type conversion; == coerces, so null == undefined, '' == 0 and [] == false are all true. Object.is differs from === only for NaN (equal to itself) and for +0 versus -0. Objects compare by reference. Every number is an IEEE 754 double: 0.1 + 0.2 !== 0.3, integers are exact only up to Number.MAX_SAFE_INTEGER (2^53 − 1), and bitwise operators convert their operands to 32-bit integers. Send 64-bit IDs as strings and use BigInt when exact large integers matter.

Promises and async/await. A promise settles once. Callbacks registered with then, and the code after an await, always run later as microtasks, even when the promise has already settled. An async function always returns a promise, and a throw inside it becomes a rejection. Sequential awaits in a loop serialize independent work; Promise.all runs it concurrently but rejects on the first failure while the other operations keep running; allSettled collects every outcome; race settles with the first promise to settle and any fulfills with the first to fulfill. array.forEach(async ...) waits for nothing.

TypeScript's model. Compatibility is structural: a value fits a type if it has the required members, whatever its declared name. Fresh object literals additionally get excess-property checks. Narrowing refines a union through control flow with typeof, instanceof, in, equality checks, discriminant fields and user-defined type predicates; assigning the leftover case to never makes a switch exhaustive. any turns checking off and spreads silently; unknown forces you to narrow before use. Generics express relationships between inputs and outputs, and constraints such as T extends { id: string } state what the body may assume.

Erasure. The compiler removes types: as assertions and type parameters perform no runtime checks. JSON.parse and response.json() return any, so validate external data where it enters, with a schema library or hand-written type guards, and keep trusted types inside.

type Result = { ok: true; value: number } | { ok: false; error: string };
function parse(raw: unknown): Result {
  if (typeof raw === 'object' && raw !== null && 'value' in raw && typeof raw.value === 'number') {
    return { ok: true, value: raw.value };
  }
  return { ok: false, error: 'invalid payload' };
}

Common misconceptions

  • "Arrow functions are just shorter functions." They have no own this or arguments and cannot be called with new, which is why they suit callbacks inside methods and fail as object methods that need this.
  • "await pauses the program." It suspends only the current async function; other code, including further event handlers, runs meanwhile.
  • "Promise.all cancels the rest when one fails." Promises cannot be cancelled; the remaining work continues and its results are ignored. Use an AbortController to actually stop requests.
  • "TypeScript validates API responses." Types vanish at runtime; as User on unvalidated JSON is an unchecked claim.
  • "const makes a value immutable." It prevents rebinding the name; the object itself can still be mutated.

How to approach it

Predict-then-run small snippets in the browser console or Node for each idea. Graduate interviews tend to check closures, this, equality and async ordering; mid-level and senior frontend interviews add typing an API client, modeling UI state with discriminated unions and explaining what the type system can and cannot guarantee. Implementing debounce, memoize, a promise pool with a concurrency limit and a typed event emitter covers most language-level practice.

Suggested order

  1. 1Read MDN "Closures" and the MDN reference for "this"; predict, then run, ten snippets covering var versus let loops, detached methods, arrow functions and bind.
  2. 2Read MDN "Inheritance and the prototype chain" and "Equality comparisons and sameness"; write down where class methods live and the result of five == comparisons before running them.
  3. 3Read the number-encoding part of the MDN Number reference; reproduce precision loss on an ID above 2^53 parsed with JSON.parse, and fix it by transporting the ID as a string.
  4. 4Read MDN "Using promises" (including the task queues versus microtasks section) and the core MDN JavaScript execution model page; predict the log order of code mixing setTimeout, then and await.
  5. 5Read the TypeScript Handbook pages Everyday Types, Narrowing, Generics and Type Compatibility; model an API response as a discriminated union handled by an exhaustive switch.
  6. 6Write a runtime validator for one API response (a schema library or hand-written type guards) and apply it at the fetch boundary so the rest of the code works with trusted types.
  7. 7Work through the Closures, Function Transformations and Promises and Time sections of LeetCode 30 Days of JavaScript in TypeScript with strict mode on.

Step 2: Check off what you can do

Tap each one you can genuinely do or explain. Each earns 10 XP.

Step 3: Go deeper

  • MDN JavaScript Guide and referenceStart here

    MDN Web Docs

    Section: Closures

    Language semantics: closures first, then the this, prototype chain, equality, number encoding and Using promises pages listed under this resource.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • The TypeScript HandbookStart here

    Microsoft (typescriptlang.org)

    Section: Narrowing

    Control-flow narrowing, discriminated unions and never-based exhaustiveness; then Everyday Types, Generics and Type Compatibility.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • JavaScript execution model (MDN)

    MDN Web Docs

    The job queue and run-to-completion model that determine promise and await ordering.

    Open(opens in a new tab)Link responded, 5 Oct 2026

Step 4: Practice

Start with the Closures, Function Transformations and Promises and Time sections of 30 Days of JavaScript; Memoize, Debounce, Promise Time Limit and Execute Asynchronous Functions in Parallel are the most instructive, and solving them in TypeScript forces you to type higher-order functions. Then solve LRU Cache using the insertion order of a Map and Time Based Key-Value Store with a typed binary search. Outside LeetCode: implement a promise pool that runs at most k tasks at once and preserves result order, and a typed event emitter whose listener argument types depend on the event name.

Record attempts on each problem’s page (+15 XP, +10 more when solved on your own).

Step 5: Test yourself

Answer each one out loud or on paper before you finish the lesson.

  1. Question 1Why do callbacks created in a for loop with var all see the same value?
  2. Question 2What is this inside a class method passed directly to setTimeout?
  3. Question 3Where does a class method live, and how is it found from an instance?
  4. Question 4How does === differ from Object.is?
  5. Question 5Why is 2 ** 53 + 1 === 2 ** 53 true?
  6. Question 6What happens to the other operations when Promise.all rejects?
  7. Question 7Why is unknown safer than any for the result of JSON.parse?
  8. Question 8What does an as assertion check at runtime?

You’re done when you can

  • Predict the output of five unseen snippets mixing closures, this and promise ordering, with at most one mistake.
  • Implement debounce and a concurrency-limited promise pool in TypeScript without looking anything up.
  • Model a server response as a discriminated union handled by an exhaustive switch that stops compiling when a variant is added.
  • Explain type erasure and point to where runtime validation happens in a small app.

Finish the lesson

How confident do you feel?

Lesson complete!

+50 XP

Reviews will come up on the Practice tab so it sticks.

Unlocks next: Browser runtime: event loop, rendering and promises

Your notes and study time

Log study time