Top 30 Easy TypeScript & Web APIs Interview Questions and Answers for Freshers
30 easy multiple-choice TypeScript & Web APIs interview questions, the ones an interviewer opens with: definitions, everyday syntax, and the quick checks that you have really used it. They come from 30 bites in the TypeScript & Web APIs library, the gentlest slice of the 125 TypeScript & Web APIs interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.
TypeScript, browser APIs, WebAssembly, PWAs
30 questions. Pick an answer, or open “Show the answer” to read it.
Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.
Question 1 of 30
Which TypeScript snippet correctly declares a string name and a numeric array using proper primitive and array type annotations?
Show the answer
Answer: a · const userName: string = "Alice"; const luckyNumbers: number[] = [7, 13, 21]
TypeScript requires lowercase string and number for primitive type annotations, and number[] correctly types an array of numbers. Option B is wrong because uppercase String and Number refer to rare built-in wrapper object types rather than the primitive value types used for standard annotations.
Read the full bite: Declare a string name and an array of lucky numbers in TypeScript
Question 2 of 30
When you write let message = 'hello' without a type annotation, what is the resulting compile-time behavior?
Show the answer
Answer: a · TypeScript infers string and later rejects message = 42 with a type error
TypeScript analyzes the right-hand side to infer string, so reassigning a number later causes a compile-time error. Distractor A is wrong because omitting an annotation does not default to any; the compiler deduces a specific static type instead.
Question 3 of 30
During a normal page navigation in the same browser tab, which object is replaced while the other persists?
Show the answer
Answer: b · Only the document object is replaced; the window object persists as the tab container.
The window object represents the browser tab and global execution context, so it persists across navigation, while the document is the in-memory DOM representation of a specific page and is rebuilt. Claiming both are replaced is a common misconception that treats window and document as the same page-level entity rather than as container versus content.
Read the full bite: What is the fundamental difference between window and document?
Question 4 of 30
In a browser script, what distinguishes a top-level var declaration from let or const?
Show the answer
Answer: b · var creates a property on the global Window object, while let and const do not, though all three are globally scoped
var creates a writable property on the global Window object, while let and const are globally scoped without becoming Window properties. Option A is a tempting misconception because let and const are indeed globally scoped; they simply do not pollute the global object.
Read the full bite: What happens when you declare var globally versus let or const?
Question 5 of 30
Which accurately describes the return values of getElementById and getElementsByClassName?
Show the answer
Answer: c · The first returns an Element or null; the second returns a live HTMLCollection.
getElementById returns a single Element or null, while getElementsByClassName returns a live HTMLCollection that automatically reflects DOM mutations. Option D is tempting because both methods query the DOM, but getElementById never returns a collection.
Read the full bite: How do you select by ID and class, and what is returned?
Question 6 of 30
When defining a User object shape for an external API that third-party modules may need to augment, why is an interface conventionally preferred over a type alias?
Show the answer
Answer: c · Interfaces support declaration merging, so multiple modules can safely contribute to the same User definition.
Interfaces are preferred because they support declaration merging, which lets separate files or plugins augment the User shape without conflicting definitions. The runtime performance claim is a common misconception because both constructs are fully erased during compilation and have zero runtime cost.
Read the full bite: Define a User object shape: interface vs type alias?
Question 7 of 30
You define a function return type as Product[] | { message: string }. What is the critical next step before using the returned value?
Show the answer
Answer: d · Use a type guard such as Array.isArray to narrow the union
Using a type guard like Array.isArray lets TypeScript narrow the union inside each branch, giving exact types and autocomplete. Simply returning the union without narrowing forces consumers to deal with both shapes manually, a subtler error that hides bugs until runtime.
Read the full bite: How do you type a function with two possible response shapes?
Question 8 of 30
You need a type alias for a function that takes a string and an optional number parameter defaulting to 5. Which is valid?
Show the answer
Answer: b · type F = (s: string, n?: number) => boolean
Function type expressions can mark parameters as optional with ? but cannot encode default values, which are implementation-only details erased at compile time. Option A is invalid because default values belong in the function body, not the type annotation.
Read the full bite: Type alias for a function with optional param and default value
Question 9 of 30
When defining a TypeScript class, which outcome occurs when you write constructor(public name: string) instead of declaring a field and assigning it manually?
Show the answer
Answer: d · TypeScript automatically declares a name property on the class and initializes it from the argument
Prefixing a constructor parameter with an access modifier tells TypeScript to generate the property declaration and assignment automatically, removing the need for manual boilerplate. The distractor about still writing name: string reflects the common misconception that parameter properties require explicit field declarations, which they do not.
Read the full bite: Create a Person class using TypeScript parameter properties
Question 10 of 30
Which sequence of checks is required to safely read .value from a getElementById result in TypeScript?
Show the answer
Answer: b · Verify the element is not null and confirm it is an HTMLInputElement before reading .value.
getElementById returns HTMLElement or null, so you must first guard against null and then narrow the type to HTMLInputElement because HTMLElement lacks the .value property. Option C is tempting because a null check feels sufficient, but TypeScript will still reject .value on the generic HTMLElement type.
Read the full bite: What is getElementById's return type and the check needed for .value?
Question 11 of 30
A button containing a nested span is clicked. If the listener is attached to the button, what is the event type and which property reliably references the button?
Show the answer
Answer: c · It is a MouseEvent; use event.currentTarget to reference the button.
The click handler receives a MouseEvent, and event.currentTarget always refers to the element that owns the listener, whereas event.target points to the actual nested element clicked—such as the span—so it would fail to reference the button itself.
Read the full bite: What is the click event's type and how to reference the button?
Question 12 of 30
When wrapping getUser(id, cb) into a Promise, which approach is correct?
Show the answer
Answer: a · Return new Promise and pass a callback that rejects on err and resolves with user
The wrapper must return a new Promise and map the error-first callback to reject on error and resolve on success. Option D is wrong because legacy callback functions typically return undefined rather than a Promise.
Read the full bite: How do you wrap a callback-based API into a Promise?
Question 13 of 30
Which pattern correctly uses fetch to retrieve JSON while handling the API's two-stage promise resolution and HTTP error behavior?
Show the answer
Answer: b · Await fetch(url), check res.ok, then await res.json() and log the parsed result
fetch resolves with a Response object rather than the final data, and it does not reject on HTTP 4xx/5xx statuses, so you must check res.ok and then await res.json() to parse the body. The most tempting distractor assumes try/catch handles HTTP errors, but fetch only rejects on network failures, not on bad response statuses.
Read the full bite: Write a fetch call and log JSON from the Response
Question 14 of 30
When using fetch, how can you ensure both network failures and HTTP 404 errors are handled by the same catch block?
Show the answer
Answer: b · Check response.ok in the then handler and throw an error if false, before parsing the body
fetch resolves for HTTP error statuses, so you must inspect response.ok and throw manually to reach the catch block. A second catch block is ineffective because 4xx and 5xx responses do not trigger rejection.
Read the full bite: How would you modify fetch to handle HTTP error statuses?
Question 15 of 30
When configuring fetch inside an async createUser function to POST JSON data, which option correctly serializes the payload and handles the response?
Show the answer
Answer: b · body is JSON.stringify(data), Content-Type is application/json, it checks response.ok, and returns await response.json()
Option B is correct because fetch requires JSON.stringify to serialize the payload and a Content-Type header so the server can parse it, plus it returns the parsed JSON rather than the raw Response. Option C is tempting but wrong because passing the raw object directly causes the body to become the string [object Object], silently breaking the request.
Read the full bite: Write a createUser function that POSTs JSON via fetch
Question 16 of 30
Which TypeScript signature correctly refactors firstElement to preserve the array's element type while returning a single element?
Show the answer
Answer: c · function firstElement<T>(arr: T[]): T
Using T[] as the return type is a tempting mistake because it keeps the array wrapper instead of extracting the element, while any and unknown erase the specific type information entirely.
Read the full bite: Refactor a function using generics to accept any array type
Question 17 of 30
Which TypeScript signature preserves the specific input type while safely allowing access to a length property in a generic utility function?
Show the answer
Answer: a · function logLength<T extends { length: number }>(arg: T): T { console.log(arg.length); return arg; }
Option A constrains T with extends so the compiler knows length exists, yet returns T to keep the exact input type. Option B is tempting because it references the same shape, but it widens the return type and erases the original identity of arrays, strings, or custom objects.
Read the full bite: Explain generic constraints and provide a length-constrained generic example
Question 18 of 30
How do Pick<User, "name" | "email"> and Omit<User, "id"> differ when derived from interface User?
Show the answer
Answer: b · They produce the same shape but Pick explicitly selects fields while Omit explicitly removes one
Both expressions yield an identical type containing name and email, but Pick communicates an allowlist intent while Omit communicates a denylist intent. Option A is tempting because it describes the general mechanics, yet it incorrectly claims the resulting shapes differ in this case.
Read the full bite: Explain Pick versus Omit with User examples
Question 19 of 30
When typing the body of a PATCH endpoint that receives only the fields a user edited, why is Partial<T> the correct choice?
Show the answer
Answer: d · It makes every property optional so the request may contain only a subset of fields
Partial<T> makes every property optional, which is exactly what a PATCH request needs because the client may send only changed fields. Option C is a tempting distractor because Partial adds optionality (?), not nullability.
Read the full bite: Describe a common use for Partial<T> and explain Required<T>
Question 20 of 30
Which TypeScript declaration derives a User type alias from a createUser function and stays synchronized with return-type changes?
Show the answer
Answer: d · type User = ReturnType<typeof createUser>
ReturnType<typeof createUser> extracts the return shape in type space so the alias stays in sync with the function. Omitting typeof, as in option C, treats createUser as a value rather than a type query and causes a compile error.
Read the full bite: Create a User type alias from a function return type
Question 21 of 30
Which choice best explains why sessionStorage is preferred over localStorage for a multi-step checkout draft that should not leak across tabs?
Show the answer
Answer: c · sessionStorage is isolated to a single tab, preventing cross-tab data leakage
sessionStorage adds a tab-level partition, so data in one tab is invisible to another tab on the same origin, whereas localStorage is shared across all tabs. Option A is tempting but misidentifies the boundary: sessionStorage is destroyed when the tab closes, not simply when the browser restarts.
Read the full bite: What is the core difference between localStorage and sessionStorage?
Question 22 of 30
Which approach correctly stores and retrieves a typed object in localStorage?
Show the answer
Answer: d · Use setItem with JSON.stringify, then getItem, check for null, parse in try-catch, and cast to an interface
localStorage persists only strings, so you must stringify on write and parse on read, but you must also check for null before parsing because getItem returns null when a key is missing. Option C is tempting because it includes serialization and typing, yet skipping the null check causes a runtime error whenever the key does not exist.
Read the full bite: How do you store and retrieve a TypeScript object in localStorage?
Question 23 of 30
What is the primary purpose of the state object passed to history.pushState?
Show the answer
Answer: a · To store data tied to the history entry and retrieve it later through popstate
The state object stores serializable data tied to a specific history entry and is surfaced through the popstate event when the user navigates back or forward; it is never sent to the server, unlike query parameters or request payloads.
Read the full bite: Programmatically change SPA URL without reload and what is state for?
Question 24 of 30
You need to process a large JSON payload without blocking UI updates. Which approach actually uses a separate browser thread?
Show the answer
Answer: c · Instantiating a Worker and passing data via postMessage
Web Workers run JavaScript in a dedicated background thread and communicate with the main thread via postMessage, preventing UI blocking. setTimeout, async/await, and requestIdleCallback all schedule work on the main thread, so CPU-intensive tasks will still freeze the interface.
Read the full bite: Which Web API offloads expensive work from the main UI thread?
Question 25 of 30
In a news PWA, a user opens a previously visited article while offline. How does the Service Worker make this possible?
Show the answer
Answer: c · It intercepts the article fetch request and returns the matching cached response.
The Service Worker acts as a programmable network proxy that intercepts fetch requests and can decide to return cached assets when the network is unavailable. Option D is a common misconception because Service Workers run in a separate worker context and cannot manipulate the DOM directly.
Read the full bite: What is a Service Worker's role and key PWA capability?
Question 26 of 30
When programmatically changing a video element's source to a new URL, which approach correctly ensures the browser loads the new media?
Show the answer
Answer: c · Assign the new URL to video.src and then call video.load()
Setting video.src only updates the resource URL; video.load() is required to reset the media controller and begin fetching the new stream. Option D omits the necessary load() call, while option B incorrectly treats currentSrc as writable and option A assumes innerHTML mutations trigger resource selection automatically.
Read the full bite: How do you programmatically play, pause, and dynamically set a video source?
Question 27 of 30
When drawing a filled circle on a canvas, what distinguishes the correct approach from drawing a filled rectangle?
Show the answer
Answer: a · Circles must be defined with a path method before filling, while rectangles use a direct primitive function
The Canvas API provides primitive rectangle functions but requires path methods like arc() for circles. Distractor D is wrong because canvas relies on immediate mode JavaScript commands, not declarative SVG markup.
Read the full bite: Get canvas 2D context and draw a filled circle
Question 28 of 30
Which approach correctly uses async/await to request webcam access and handle specific failure modes in TypeScript?
Show the answer
Answer: d · Use try/catch, assign the stream to video.srcObject, and branch on specific DOMException names
The correct approach assigns the MediaStream to srcObject rather than src, because src expects a string URL, and branches on specific DOMException names to distinguish user denial from missing hardware. The most tempting distractor includes try/catch but uses src, which prevents the video element from rendering the live stream.
Question 29 of 30
Why is enabling the strict option usually the highest-priority change in a new tsconfig.json?
Show the answer
Answer: d · It is an umbrella flag enabling several checks like noImplicitAny and strictNullChecks
strict turns on a family of safety checks such as strictNullChecks and noImplicitAny, which is where TypeScript catches the most bugs. It does not minify output, choose the target, or skip lib checks; that last is skipLibCheck.
Read the full bite: First compilerOptions to set after tsc --init
Question 30 of 30
While migrating a legacy Backbone app to TypeScript strict mode, model.get requires null guards across hundreds of views. Which adjustment lets the project compile while keeping strict enabled?
Show the answer
Answer: b · Disable strictNullChecks, accepting that null-safety will only be enforced at runtime
Disabling strictNullChecks allows the project to compile by relaxing null-safety on external APIs and DOM access while keeping the rest of strict enabled. Turning off the strict master switch entirely is the red-flag answer because it abandons all type safety instead of targeting the specific sub-flag causing the migration pain.
Read the full bite: What is tsconfig strict, and which sub-flag to relax for legacy?
Could you explain these out loud?
That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.