10 TypeScript Interview Questions That Separate Juniors From Seniors
Some links in this article are affiliate links. We earn a commission at no extra cost to you when you purchase through them. Full disclosure.
TypeScript interviews arenβt about syntax β any developer can look that up. They test whether you understand the type system deeply enough to design safe, maintainable code. These 10 questions are the ones that reveal that understanding. (New to TypeScript? Start with What is TypeScript first.)
1. Whatβs the difference between type and interface?
Both define object shapes. The practical differences:
interfacesupports declaration merging (defining the same interface twice merges them)typesupports unions, intersections, and mapped typesinterfacecan be extended withextends,typeuses&
Senior answer: βI use interface for public API contracts (theyβre extendable) and type for everything else (unions, utility types, complex compositions).β
2. Explain type narrowing
Type narrowing is how TypeScript refines a broad type to a more specific one within a code block:
function process(input: string | number) {
if (typeof input === 'string') {
// TypeScript knows input is string here
return input.toUpperCase();
}
// TypeScript knows input is number here
return input.toFixed(2);
}
Narrowing works with: typeof, instanceof, in, equality checks, and custom type guards.
3. What are generics and when do you use them?
Generics let you write functions/types that work with any type while preserving type safety:
// Without generics β loses type info
function first(arr: any[]): any { return arr[0]; }
// With generics β preserves type
function first<T>(arr: T[]): T { return arr[0]; }
const num = first([1, 2, 3]); // type: number
const str = first(['a', 'b']); // type: string
When to use: When a function/class needs to work with multiple types but the relationship between input and output types matters. Generics come up constantly in React interview questions too, especially when typing custom hooks and higher-order components.
4. Whatβs the difference between any, unknown, and never?
anyβ disables type checking. Anything goes. Avoid it.unknownβ type-safeany. You must narrow it before using it.neverβ represents values that never occur (exhaustive checks, functions that throw).
function handleValue(val: unknown) {
// val.toUpperCase(); // β Error β must narrow first
if (typeof val === 'string') {
val.toUpperCase(); // β
Narrowed to string
}
}
function assertNever(x: never): never {
throw new Error(`Unexpected value: ${x}`);
}
5. Explain utility types: Pick, Omit, Partial, Required
interface User {
id: number;
name: string;
email: string;
role: string;
}
type UserPreview = Pick<User, 'id' | 'name'>; // { id, name }
type UserWithoutEmail = Omit<User, 'email'>; // { id, name, role }
type PartialUser = Partial<User>; // all fields optional
type RequiredUser = Required<Partial<User>>; // all fields required again
Senior follow-up: βCan you build a custom utility type?β
type Readonly<T> = { readonly [K in keyof T]: T[K] };
6. Whatβs a discriminated union?
A pattern where each type in a union has a common literal field that TypeScript uses for narrowing:
type Success = { status: 'success'; data: string };
type Error = { status: 'error'; message: string };
type Result = Success | Error;
function handle(result: Result) {
switch (result.status) {
case 'success': return result.data; // TypeScript knows it's Success
case 'error': return result.message; // TypeScript knows it's Error
}
}
This is the most important TypeScript pattern for modeling domain logic safely. Libraries like Zod use discriminated unions extensively for schema validation β see Zod vs Yup for how they compare.
7. How does as const work?
as const makes TypeScript infer the narrowest possible type:
const config = { api: '/users', method: 'GET' };
// type: { api: string; method: string }
const config = { api: '/users', method: 'GET' } as const;
// type: { readonly api: '/users'; readonly method: 'GET' }
Useful for: configuration objects, action types, and anywhere you want literal types instead of broad string/number types.
8. Whatβs the difference between extends in generics vs interfaces?
In interfaces, extends means inheritance:
interface Animal { name: string }
interface Dog extends Animal { breed: string }
In generics, extends means constraint:
function getLength<T extends { length: number }>(item: T): number {
return item.length; // T must have a length property
}
9. How do you type async functions and Promises?
// Function that returns a Promise
async function fetchUser(id: number): Promise<User> {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
// Extracting the resolved type
type ResolvedUser = Awaited<ReturnType<typeof fetchUser>>; // User
10. What TypeScript config settings do you always enable?
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"exactOptionalPropertyTypes": true
}
}
Why each matters:
strictβ enables all strict checks (nullable, implicit any, etc.)noUncheckedIndexedAccessβ array access returnsT | undefinedinstead ofTnoImplicitReturnsβ every code path must return a valueexactOptionalPropertyTypesβundefinedand βmissingβ are different
The candidate who can explain why they enable these settings understands TypeScript at a senior level.
Related: TypeScript Cheat Sheet Β· TypeScript Complete Guide Β· React Interview Questions
Go deeper: Pluralsight has advanced TypeScript courses covering generics, conditional types, and real-world patterns. Start a free 10-day trial.