Key Takeaways
- TypeScript interviews test how you think about correctness at the type level, not just whether you can annotate variables.
- Interfaces and type aliases overlap heavily, but interviewers expect you to know where they diverge.
- Generics questions are really testing whether you can write reusable code without sacrificing type safety.
- Knowing when to use unknown instead of any is one of the more common signals of TypeScript maturity.
- Utility types like Partial, Pick, and Omit come up constantly in real code, and interviewers use them to test whether you actually work in TypeScript day to day.
TypeScript has become close to a default expectation for frontend and Node.js roles, which means
TypeScript interview questions increasingly test depth rather than basic familiarity. Interviewers
aren't checking whether you know how to write let x: string — they're checking whether you reach
for the type system to prevent real bugs, or whether you're writing JavaScript with type annotations
bolted on as an afterthought.
Why Companies Test TypeScript Specifically
A codebase's type safety is only as strong as the discipline of the people writing it. It's entirely
possible to write TypeScript that provides almost no real safety — liberal use of any, loosely
typed function signatures, ignored compiler warnings. Interviewers ask pointed TypeScript questions
specifically to filter for candidates who use the type system as a design tool, not just a linting
formality.
Type System Fundamentals
"What's the difference between an interface and a type alias?" Both can describe the shape of an
object, and for most everyday use they're interchangeable. The real differences: interfaces support
declaration merging (you can declare the same interface twice and it merges the members), and
interfaces can be extended with extends in a way that's slightly more idiomatic for object shapes,
while type aliases can represent unions, primitives, and more complex compositions that interfaces
can't directly express.
interface User {
id: string;
name: string;
}
type ID = string | number; // type aliases handle unions; interfaces can't
"What is type narrowing, and how does it work?" Narrowing is how TypeScript progressively
refines a broader type to a more specific one within a code path, usually via typeof checks,
instanceof, truthiness checks, or discriminated unions.
function printLength(value: string | string[]) {
if (typeof value === 'string') {
console.log(value.length); // narrowed to string here
} else {
console.log(value.length); // narrowed to string[] here
}
}
Generics Questions
Generics are one of the most reliable ways interviewers separate surface-level TypeScript users from people who write genuinely reusable, type-safe code.
"Write a generic function that returns the first element of an array, correctly typed."
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = first([1, 2, 3]); // inferred as number | undefined
const str = first(['a', 'b']); // inferred as string | undefined
A good follow-up discussion point: without the generic <T>, you'd either have to write this
function once per type, or type the parameter and return value as any, silently losing all type
safety at the call site.
"When would you constrain a generic with extends?" When the generic type needs to guarantee
some minimum shape to be usable inside the function:
function getProperty<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
This constrains K to only the actual keys of T, so calling getProperty(user, "invalidKey")
fails at compile time rather than silently returning undefined at runtime.
When explaining generics, connect the answer back to a concrete problem generics solve — avoiding duplicated code across types, or catching an invalid key access at compile time — rather than just describing generic syntax in the abstract.
Utility Types
These come up constantly in real code, which makes them a favorite interview topic because they distinguish people who actually write TypeScript daily from people who've only studied it.
Partial<T>— makes all properties optional. Common in update functions where only some fields change.Pick<T, K>— constructs a type with only a subset of properties.Omit<T, K>— the inverse ofPick; excludes specified properties.Record<K, V>— builds an object type with keys of typeKand values of typeV, useful for lookup maps.
interface User {
id: string;
name: string;
email: string;
}
type UserUpdate = Partial<Omit<User, 'id'>>; // name and email optional, id excluded entirely
Advanced Questions
"What's the difference between any and unknown?" any disables type checking entirely for
that value — you can call any method or access any property with no compiler complaint. unknown
also accepts any value, but forces you to narrow the type before doing anything with it, preserving
safety while still allowing genuinely dynamic values. Preferring unknown over any when the type
genuinely isn't known ahead of time is a strong signal of TypeScript maturity.
"What is a discriminated union, and why is it useful?"
type Response = { status: 'success'; data: string } | { status: 'error'; message: string };
function handle(res: Response) {
if (res.status === 'success') {
console.log(res.data); // TypeScript knows data exists here
} else {
console.log(res.message); // and message exists here
}
}
The shared status field acts as a discriminant, letting TypeScript narrow the union automatically
based on a runtime check — a pattern that shows up constantly in API response typing and state
machines.
The TypeScript questions that separate strong candidates aren't about obscure syntax — they're about whether the type system is doing real work in your code, or just decorating it.
TypeScript in Practice
Expect at least one question about compiler configuration or team conventions:
strictmode enables a bundle of stricter checks (strictNullChecks,noImplicitAny, and others) — know that turning it on incrementally on an existing codebase is a common, and sometimes painful, real-world task.- Why avoid
anyin code review — because it silently disables checking for everything that flows through that value, often spreading type-unsafety further than the original line where it was introduced.
Common Mistakes
- Treating
anyandunknownas interchangeable - Defaulting to
interfaceortypeout of habit rather than knowing why one fits better in a given case - Writing generic functions with no constraints when the logic actually depends on the type having certain properties
- Being unable to explain a compiler error message in your own words, rather than just fixing it by trial and error
How to Prepare
Review a recent pull request or personal project and look specifically for places you used any, a
loosely typed function signature, or a type assertion (as) to work around a compiler complaint
rather than resolve it properly. Being able to explain why you made that trade-off — or better,
revisiting it with a stronger typed solution — gives you real, specific material for an interview
instead of only textbook examples.
Put this into practice.
Start a free AI-powered mock interview — real follow-up questions, instant feedback, no card required.