TypeScript Interview Questions — Practice with Real Quiz Questions
Reviewed by Mark Dickie · Last updated
TypeScript is a statically typed superset of JavaScript that compiles to plain JavaScript, adding optional type annotations, interfaces, and compile-time error checking. For interviews, you should know the type system (primitives, unions, intersections, literal types), generics and constraints, type narrowing (typeof, instanceof, in, user-defined type guards), utility types (Partial, Pick, Omit, Record, ReturnType), and the structural typing model that distinguishes TypeScript from nominally typed languages like Java or C#. Expect questions on configuration options like strict mode, tsconfig.json settings, declaration files (.d.ts), and the differences between interface and type aliases.
| Topic | What to study |
|---|---|
| Generics | Constraints with extends, default type parameters, conditional types |
| Type narrowing | Discriminated unions, in operator, custom type guards |
| Utility types | Partial<T>, Omit<T,K>, Record<K,V>, ReturnType<T> |
| Structural typing | Shape compatibility vs. nominal typing |
| tsconfig | strict, noImplicitAny, target, moduleResolution |
| Declaration merging | How interfaces with the same name combine |
What does a TypeScript interview typically test?
Most TypeScript interviews focus on practical type-level problem solving rather than trivia. You may be asked to write a generic function, build a utility type from scratch, or debug why the compiler rejects an assignment that looks correct at first glance. Senior-level roles go further into conditional types, mapped types, template literal types, and variance. The interview usually mixes whiteboard or live-coding with conceptual questions about why a particular type annotation is needed.
What is the difference between interface and type in TypeScript?
Both can describe object shapes, and in most cases they are interchangeable. Key differences:
- Interfaces support declaration merging — declaring the same interface name twice merges their members. Type aliases do not.
- Type aliases can represent unions, intersections, tuples, and primitive aliases. Interfaces are limited to object and function shapes.
- Interfaces can be extended with
extends, and types can be combined with the&intersection operator. Both approaches work for composition. - Error messages tend to read more cleanly for interfaces in complex scenarios, since the compiler preserves the interface name rather than expanding the alias inline.
How does TypeScript's structural typing affect interview answers?
TypeScript checks shape compatibility, not name identity. An object is assignable to a type if it has all the required properties with matching types — extra properties are allowed in most contexts (except direct object literals, where excess property checking applies). This is the single biggest conceptual difference from languages like Java, and interviewers probe it through questions about assignability, function parameter bivariance, and when to use branding or tagging to recover nominal-like behavior.
Key facts
- Tarmac has 93 TypeScript interview questions on this topic, 10 of them on this page, at difficulty 2–4 of 5.
- Tarmac last reviewed these TypeScript interview questions on 18 August 2026.
At a glance
| Questions | 10 shown · 93 in the bank |
|---|---|
| Difficulty | 2–4 of 5 |
| Formats | Multiple answer, True / false, Code output, Fill in the blank, Coding exercise, Ordering, Multiple choice, Find the bug, Short answer, Flashcard |
| Interactive | 1 run your code against tests, in the app |
What you'll review
- partial required
- primitives
- generic functions
- pick omit
- exhaustiveness
- discriminated unions
- mapped types
Practice questions
TypeScript/utility-types/partial-required
Which of these are built-in TypeScript utility types?#
Options
Pick every one that applies.
Show answer
Partial<T>, Pick<T, K>, and Readonly<T> are all built-in utility types — but Maybe<T> is not. Maybe comes from some functional-programming libraries rather than TypeScript's standard library, so the compiler does not provide it out of the box.
Partial, Pick, and Readonly are built in. Maybe is not part of TypeScript's standard library (it comes from some FP libraries).
TypeScript/types-basics/primitives
TypeScript types are erased during compilation and have no presence in the emitted JavaScript.#
Options
Show answer
True. Type annotations, interfaces, and generics are erased during compilation and leave no trace in the emitted JavaScript. That is why you cannot inspect a TypeScript type at runtime — there is nothing left to check, so you must reach for runtime guards like typeof or a validation library instead.
Type annotations, interfaces, and generics are erased at compile time. That is why you cannot check a type at runtime — there is nothing left to inspect (you must use runtime guards like typeof or a validation library).
TypeScript/generics/generic-functions
What does this log?#
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
console.log(first([10, 20, 30]));Show answer
10
The generic first infers T = number from the argument and returns arr[0], which is 10. Types are erased at runtime; the behaviour is just plain array indexing.
TypeScript/utility-types/pick-omit
_____<User, 'id' | 'name'> keeps only those two keys, while _____<User, 'password'> keeps everything except that one.#
Show answer
**Pick**<User, 'id' | 'name'> keeps only those two keys, while **Omit**<User, 'password'> keeps everything except that one.
Pick selects a subset of keys; Omit removes them. They're complements — Omit<T, K> is Pick<T, Exclude<keyof T, K>>.
TypeScript/generics/generic-functions
Implement pluck(items, key): given an array of objects and a key, return the array of values at that key. Type it generically so key is constrained to keyof T and the return type is T[K][].#
Starter code
function pluck(items: unknown[], key: string): unknown[] {
// TODO: generic signature + implementation
return [];
}Your solution must pass
- plucks names
This one is written and run, not read. Solve it in the app and your code is executed against these tests and the hidden ones.
TypeScript/narrowing/exhaustiveness
You're handling a Shape discriminated union exhaustively. Order the steps that make the compiler enforce exhaustiveness.#
Put these in order
Show answer
To make the compiler enforce exhaustiveness, follow these steps in order:
switch (shape.kind)on the discriminant- Handle each known
kindin its owncase - Assign the value to a
neverindefault
If a new variant is later added without a case, the default assignment to never becomes a compile error.
Switch on the discriminant, handle each variant, then in default assign the narrowed value to a const _exhaustive: never — if a new variant is added later, that assignment becomes a compile error.
TypeScript/utility-types/partial-required
Which of the following mapped types is exactly equivalent to TypeScript's built-in Partial<T> utility type?#
Options
Show answer
type MyPartial<T> = { [P in keyof T]?: T[P] }; is exactly equivalent to Partial<T>. It maps over every key of T and applies the ? modifier, making each property optional while preserving its original type. Without the ?, the properties stay required; using -? would strip optionality (like Required<T>); and T[P] | undefined alone keeps properties required but unioned with undefined, which is not the same as optional.
TypeScript's built-in Partial<T> makes all properties optional by mapping over the keys with { [P in keyof T]?: T[P] }. The question asks candidates to reconstruct it manually. Option (a) is correct: it maps every key to an optional property of the same type. Option (b) forgets the ? modifier (that's Readonly<T>-style without readonly). Option (c) uses -? which REMOVES optionality (that's Required<T>). Option (d) maps to T[P] | undefined without the ? modifier, which makes every property required but explicitly typed as T[P] | undefined — subtly different from optional.
TypeScript/utility-types/partial-required
The following DeepPartial<T> utility type is intended to recursively make all properties at every nesting level optional. It has exactly one bug. Identify the buggy line.#
type DeepPartial<T> =
T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: never;Show answer
The bug is on line 4.
The code defines DeepPartial<T> which recursively makes all nested properties optional. On line 2, the conditional check should be T extends object (not T extends Object — though that works too, but the real bug is elsewhere). Actually the bug is on line 3: the recursive mapped type uses T[P] instead of DeepPartial<T[P]> for the value — wait, let's read carefully. Line 3 is [P in keyof T]?: DeepPartial<T[P]> — that looks correct. The actual bug is on line 2: T extends object ? { ... } : T — for non-object primitives this is fine. The real bug in this snippet is on line 4: the else branch returns never instead of T. When T is a primitive like string or number, DeepPartial<T> should return T itself, not never. So never on line 4 is the buggy line.
TypeScript/narrowing/discriminated-unions
What is a discriminated union and why is it useful?#
Show answer
A discriminated (tagged) union is a union of object types that share a common literal property — the discriminant. Switching on that property lets TypeScript narrow the value to one exact member, so you can handle each case type-safely and get exhaustiveness checking for free.
The shared literal field (e.g. type: 'circle' | 'square') is what lets the compiler narrow inside a switch. Adding a never default then enforces that every member is handled.
TypeScript/advanced-types/mapped-types
For type T = { a: 1; b: 2 }, what does keyof T produce?#
Show answer
'a' | 'b' — a union of T's property keys (as string literal types).
keyof turns an object type's keys into a union of literal types. Combined with generics (<K extends keyof T>) it powers type-safe property access like Pick and get(obj, key).
Sources
The official documentation these questions are checked against:
Related interview questions
The other 83 questions
This page shows 10. A free account opens the rest and marks your answers, which a page of answers can't do. Miss one and it returns a few days later, then a week after that, until you stop missing it.
Free · the whole bank · 100 graded answers per 30 days · written feedback and job-ad quizzes on the paid plan