TypeScript Interview Questions for Senior Developers (2026)

A practical set of TypeScript interview questions for senior frontend developer interviews, with coding problems on generics, unions, utility types, and React TypeScript.
作者
GreatFrontEnd Team
10 分钟阅读
Jun 3, 2026
TypeScript Interview Questions for Senior Developers (2026)

This guide is a practical set of TypeScript interview questions for senior frontend developers. In 2026, senior TypeScript interviews are less about defining Partial<T> and more about using the type system to model product states, prevent invalid component APIs, and make refactors safer.

If you are preparing for TypeScript interview questions for experienced roles, focus on code problems. Interviewers want to see how you design constraints, how you narrow unsafe data, and when you choose a simple type over a clever one.

If you want more hands-on practice after this guide, use GreatFrontEnd's TypeScript interview questions.

How senior TypeScript interviews are different

At junior and mid-level, TypeScript questions often check syntax: interface vs type, unknown vs any, optional properties, or basic generics.

At senior and staff level, the prompt usually sounds more like production code:

  • "This component accepts invalid prop combinations. Fix the API."
  • "This API response has five states and the UI keeps missing one."
  • "This helper loses literal types and breaks autocomplete."
  • "This design-system type is too permissive. Make invalid variants impossible."
  • "This utility type works, but it is unreadable. Would you keep it?"

That is the pattern behind the TypeScript coding interview questions below.

1. Model async UI state with discriminated unions

How it appears in an interview: "Our dashboard uses isLoading, error, and data, but invalid states keep slipping through. Refactor the type."

type RemoteData<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: Error };
function assertNever(value: never): never {
throw new Error(`Unhandled state: ${JSON.stringify(value)}`);
}
function renderUsers(state: RemoteData<Array<{ id: string; name: string }>>) {
switch (state.status) {
case "idle":
return "Choose a team";
case "loading":
return "Loading users";
case "success":
return state.data.map((user) => user.name).join(", ");
case "error":
return state.error.message;
default:
return assertNever(state);
}
}

What interviewers look for: You should remove impossible states instead of documenting them. success must always have data; error must always have error; loading should not accidentally carry stale data unless that is an explicit product decision.

The senior signal is exhaustiveness. If a future engineer adds { status: 'refreshing' }, the assertNever line makes incomplete rendering logic fail at compile time.

2. Write a generic pick helper without losing key safety

How it appears in an interview: "Implement pick(obj, keys) so keys must exist on the object and the return type only contains those keys."

function pick<T extends object, K extends keyof T>(
obj: T,
keys: readonly K[],
): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) {
result[key] = obj[key];
}
return result;
}
const user = {
id: "u_1",
name: "Ada",
role: "admin",
active: true,
};
const summary = pick(user, ["id", "name"] as const);
// summary is { id: string; name: string }

What interviewers look for: This tests generic constraints and keyof. A weaker answer uses string[] for keys and returns Partial<T>, which loses the reason TypeScript is useful here. A strong answer preserves the exact key union.

The follow-up is usually about mutation. The cast inside the function is acceptable because JavaScript object construction is dynamic, but the public API remains precise. Senior candidates can explain that boundary instead of pretending no assertion is ever allowed.

3. Type an API patch payload with utility types

How it appears in an interview: "We need an endpoint that updates a user profile. It should allow name, email, and timezone, but never id, createdAt, or role."

type User = {
id: string;
name: string;
email: string;
timezone: string;
role: "member" | "admin";
createdAt: string;
};
type EditableUserFields = Pick<User, "name" | "email" | "timezone">;
type UpdateUserPayload = Partial<EditableUserFields>;
async function updateUser(id: User["id"], payload: UpdateUserPayload) {
return fetch(`/api/users/${id}`, {
method: "PATCH",
body: JSON.stringify(payload),
});
}
updateUser("u_1", { timezone: "Asia/Kolkata" });

What interviewers look for: Utility types should express intent. Partial<User> is too broad because it allows protected fields. Pick plus Partial says, "Only these fields are editable, and each is optional in a patch."

This is one of the most common TypeScript coding questions because it mirrors real frontend work: form models, DTOs, optimistic updates, and API client boundaries.

4. Use conditional types and infer to unwrap async results

How it appears in an interview: "Given a service function, derive the resolved response type without copying it manually."

async function getCurrentUser() {
return {
id: "u_1",
name: "Grace",
permissions: ["billing:read", "team:write"] as const,
};
}
type AsyncReturn<T> = T extends (...args: infer _Args) => Promise<infer R>
? R
: never;
type CurrentUser = AsyncReturn<typeof getCurrentUser>;
function canEditTeam(user: CurrentUser) {
return user.permissions.includes("team:write");
}

What interviewers look for: This tests whether you understand conditional types as relationships between inputs and outputs. infer R captures the resolved value from a promise-returning function.

A practical follow-up: TypeScript already has ReturnType<T> and Awaited<T>, so this can also be written as:

type CurrentUser = Awaited<ReturnType<typeof getCurrentUser>>;

The senior answer names the built-in utility and explains when a custom helper is still useful.

5. Build event names with template literal and mapped types

How it appears in an interview: "Create a typed event map for a settings object. Each key should produce an on<Key>Changed handler."

type ChangeHandlers<T extends object> = {
[K in keyof T as `on${Capitalize<string & K>}Changed`]: (
nextValue: T[K],
) => void;
};
type Settings = {
theme: "light" | "dark";
pageSize: 25 | 50 | 100;
showArchived: boolean;
};
type SettingsHandlers = ChangeHandlers<Settings>;
const handlers: SettingsHandlers = {
onThemeChanged: (theme) => console.log(theme),
onPageSizeChanged: (pageSize) => console.log(pageSize),
onShowArchivedChanged: (showArchived) => console.log(showArchived),
};

What interviewers look for: This combines mapped types, key remapping, template literal types, and indexed access types. It is a strong senior prompt because the runtime idea is simple, but the type-level transformation requires precision.

The judgment part matters too. This pattern is useful for design-system APIs, event maps, analytics names, and generated clients. It is probably overkill for one local component.

6. Type mutually exclusive React props

How it appears in React TypeScript interview questions: "Create a button that can behave like a link or a real button, but never both."

type BaseProps = {
children: React.ReactNode;
variant?: "primary" | "secondary";
};
type LinkButtonProps = BaseProps & {
href: string;
onClick?: never;
};
type ActionButtonProps = BaseProps & {
href?: never;
onClick: () => void;
};
type ButtonProps = LinkButtonProps | ActionButtonProps;
function Button(props: ButtonProps) {
if (props.href !== undefined) {
return <a href={props.href}>{props.children}</a>;
}
return <button onClick={props.onClick}>{props.children}</button>;
}

What interviewers look for: Prop types can define product constraints instead of merely documenting them. never prevents callers from passing both href and onClick, and the href check narrows the union inside the component.

This is a better answer than a single prop bag with href?: string and onClick?: () => void, because the weak version makes every invalid combination somebody else's runtime problem.

7. Create a type-safe component variant map

How it appears in an interview: "We have variants in a design system. Keep the object literal narrow, but verify that every variant exists."

type ButtonVariant = "primary" | "secondary" | "danger";
const buttonClasses = {
primary: "bg-blue-600 text-white",
secondary: "bg-slate-100 text-slate-900",
danger: "bg-red-600 text-white",
} satisfies Record<ButtonVariant, string>;
function getButtonClass(variant: ButtonVariant) {
return buttonClasses[variant];
}

What interviewers look for: This problem checks whether you know the difference between annotation and validation. satisfies verifies the object conforms to Record<ButtonVariant, string> while preserving useful inference from the original object.

In a senior interview, expect a follow-up: "What happens when someone adds ghost to ButtonVariant?" The object must now include ghost, so the compiler catches the incomplete design-system map.

8. Explain when unknown is better than any

How it appears in an interview: "We parse JSON from local storage. Type it safely."

function parseJson(value: string): unknown {
return JSON.parse(value);
}
type Preferences = {
theme: "light" | "dark";
};
function isPreferences(value: unknown): value is Preferences {
return (
typeof value === "object" &&
value !== null &&
"theme" in value &&
(value.theme === "light" || value.theme === "dark")
);
}
const parsed = parseJson(localStorage.getItem("preferences") ?? "{}");
if (isPreferences(parsed)) {
parsed.theme;
}

What interviewers look for: any says "trust me" and disables checking. unknown says "prove it first." Senior TypeScript work often happens at boundaries: network responses, storage, third-party scripts, feature flags, analytics payloads, and CMS content.

The strong answer pairs unknown with a narrowing function or schema validator. TypeScript cannot make untrusted runtime data safe by itself.

9. Choose literal unions over enums for frontend constants

How it appears in an interview: "Our app has several status constants. Should we use an enum, a union type, or an as const object?"

const ORDER_STATUS = {
Draft: "draft",
Paid: "paid",
Shipped: "shipped",
Cancelled: "cancelled",
} as const;
type OrderStatus = (typeof ORDER_STATUS)[keyof typeof ORDER_STATUS];
function getStatusLabel(status: OrderStatus) {
switch (status) {
case ORDER_STATUS.Draft:
return "Draft";
case ORDER_STATUS.Paid:
return "Paid";
case ORDER_STATUS.Shipped:
return "Shipped";
case ORDER_STATUS.Cancelled:
return "Cancelled";
}
}

What interviewers look for: In frontend code, string literal unions and as const objects often fit better than regular enums because they keep API values as plain strings and compose cleanly with other type utilities.

A senior answer should not turn this into a rule. Enums can still be useful in shared TypeScript codebases, but for UI state, analytics event names, API statuses, and component variants, literal unions are usually easier to compose with mapped types, discriminated unions, and template literal types.

Senior TypeScript preparation checklist

Use this checklist for TypeScript interview questions for 5 years experience and above:

  1. Practice discriminated unions until you can model async state, reducers, and component modes without invalid combinations.
  2. Write generic helpers using keyof, indexed access types, and constrained type parameters.
  3. Know the common utility types: Partial, Required, Pick, Omit, Record, ReturnType, Parameters, and Awaited.
  4. Be able to read conditional types with infer, even if you do not write them every day.
  5. Use mapped types and template literal types when an API can be derived from another type.
  6. In React, type props as constraints: mutually exclusive props, controlled vs uncontrolled props, required children, and exact event handlers.
  7. Prefer unknown at unsafe boundaries and narrow before use.
  8. Know when as const and literal unions are cleaner than runtime enums.
  9. Explain tradeoffs. A senior answer is allowed to say, "This type is correct, but too complex for this codebase."

The best senior TypeScript answers are practical. They prevent invalid states, preserve inference, and make the next refactor less risky.

When practicing TypeScript coding questions, do not memorize every utility type in isolation. Start with a real constraint: which states are impossible, which keys are allowed, which component props conflict, which runtime values are untrusted. Then use TypeScript to encode that constraint clearly.

For more practice, head to GreatFrontEnd's TypeScript interview questions and work through problems with the same mindset: code first, types as guardrails, and explanations that connect back to production frontend work.

相关文章

TypeScript for React Developers: 12 Common Mistakes and Best PracticesMaster TypeScript React best practices by avoiding these 12 common mistakes. Learn proper component typing, hooks patterns, and API integration techniques.
JavaScript Interview Questions for 5+ Years of ExperienceExplore advanced JavaScript interview questions and answers designed for engineers with 5+ years of experience, curated by big tech senior engineers.
50 React.js Interview Questions for Experienced Developers50 React JS interview questions for experienced developers. Explore detailed solutions to enhance your preparation for 2025 job interviews