LearnFrenzy
Sign in Take a free test

Utility and Advanced Types · Lesson 17 of 17

TypeScript Interview Questions

7 min read Updated Nov 8, 2026 Saurabh Samir

Angular, React and Node interviews now assume TypeScript. Interviewers rarely ask for trivia; they check whether you understand what the type system does (and doesn't) guarantee. Below are the questions that come up most, grouped from fundamentals to advanced, each with a short answer and code where it helps.

In this lesson

  • Fundamentals: what TypeScript is, any vs unknown, type vs interface
  • Everyday: narrowing, generics, utility types
  • Advanced: conditional types, satisfies, declaration files
  • TypeScript with React and Node

Fundamentals

1. What is TypeScript, and does it make code faster?

A superset of JavaScript that adds static types checked at compile time. Types are erased, so the output is plain JavaScript with the same run-time speed. The gain is in catching bugs earlier and in better editor tooling.

2. any vs unknown vs never

function parse(json: string): unknown {
  return JSON.parse(json);
}

const data = parse('{"name":"Asha","score":91}');
// data.name;                                      // error: data is unknown – you must check first
if (typeof data === "object" && data !== null && "name" in data) {
  console.log(String(data.name));
}

function fail(message: string): never {            // never returns
  throw new Error(message);
}
try {
  fail("unreachable state");
} catch (e) {
  console.log((e as Error).message);
}

Output

Asha
unreachable state

any switches checking off; unknown accepts anything but forces you to narrow before use; never is the type with no values (functions that never return, exhausted unions).

3. type vs interface?

Both describe object shapes. Interfaces can be reopened (declaration merging) and extended with extends; type aliases can also name unions, tuples, primitives and mapped or conditional types. A common team rule: interfaces for object shapes and public APIs, types for unions and computed types.

4. Does TypeScript check data at run time?

No. An API response typed as User is only assumed to be a User. Validate external data (API responses, form input, environment variables) with a schema library such as zod, and derive the type from the schema.

Everyday TypeScript

5. What is narrowing? Name the ways to narrow.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "rect"; w: number; h: number };

function isCircle(s: Shape): s is { kind: "circle"; radius: number } {   // user-defined type guard
  return s.kind === "circle";
}

function area(s: Shape): number {
  switch (s.kind) {                       // discriminant narrowing
    case "circle": return Math.PI * s.radius ** 2;
    case "rect": return s.w * s.h;
    default: {
      const unreachable: never = s;       // compile error if a new kind is not handled
      return unreachable;
    }
  }
}

const shapes: Shape[] = [{ kind: "circle", radius: 1 }, { kind: "rect", w: 3, h: 4 }];
console.log(shapes.map(area).map((a) => a.toFixed(2)), shapes.filter(isCircle).length);

Output

[ '3.14', '12.00' ] 1

Narrowing with typeof, instanceof, in, equality, truthiness, discriminant fields and type predicates (x is T). The never check makes a switch exhaustive.

6. Write a generic function with a constraint.

function maxBy<T extends object, K extends keyof T>(items: readonly T[], key: K): T | undefined {
  return items.reduce<T | undefined>((best, item) => (best === undefined || item[key] > best[key] ? item : best), undefined);
}

const team = [{ name: "Asha", score: 91 }, { name: "Ravi", score: 97 }, { name: "Meera", score: 88 }];
console.log(maxBy(team, "score")?.name, maxBy(team.slice(0, 0), "score"));

Output

Ravi undefined

7. Explain Partial, Pick, Omit and Record with a use case.

Partial<User> for PATCH bodies, Omit<User, "passwordHash"> for API responses, Pick<User, "id" | "name"> for list items, Record<Role, Permission[]> for lookup tables that must cover every key.

8. What's the difference between optional (x?: T) and x: T | undefined?

With ? the property may be missing entirely; with T | undefined it must be present but may hold undefined. Under exactOptionalPropertyTypes, x?: T no longer accepts an explicit undefined.

Advanced

9. Implement your own ReturnType.

type MyReturnType<F> = F extends (...args: never[]) => infer R ? R : never;

function login(user: string) {
  return { user, token: "abc123", expiresIn: 3600 };
}
type Session = MyReturnType<typeof login>;

const s: Session = login("asha");
console.log(Object.keys(s), s.expiresIn / 60);

Output

[ 'user', 'token', 'expiresIn' ] 60

10. What does satisfies do?

It checks that a value matches a type without widening the value's inferred type, so you keep literal keys and values (see the previous lesson). Useful for config objects and theme tokens.

11. What is a .d.ts file? What is declaration merging?

A file with only type declarations, describing JavaScript defined elsewhere (from @types/* packages or your own declare module). Declaration merging means two interface declarations with the same name combine – that's how you add fields to Window or NodeJS.ProcessEnv.

12. Structural typing – what does it mean?

interface Point { x: number; y: number }
class Vector {
  constructor(public x: number, public y: number, public z: number) {}
}

function length2d(p: Point): number {
  return Math.hypot(p.x, p.y);
}
console.log(length2d(new Vector(3, 4, 12)));   // a Vector has x and y, so it is a Point

Output

5

Compatibility depends on shape, not on declared names. Any value with the required members fits – unlike Java or C#, which use nominal typing. (Excess property checks still apply to object literals written directly.)

TypeScript with React and Node

13. How do you type React component props and state?

// Button.tsx
type ButtonProps = {
  label: string;
  variant?: "primary" | "danger";
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
} & Omit<React.ComponentPropsWithoutRef<"button">, "onClick">;   // plus every native button prop

export function Button({ label, variant = "primary", ...rest }: ButtonProps) {
  return <button className={`btn btn-${variant}`} {...rest}>{label}</button>;
}

// state: inferred from the initial value, or given explicitly when it can be null
const [user, setUser] = useState<User | null>(null);
const inputRef = useRef<HTMLInputElement>(null);

Type props as a plain function parameter rather than React.FC; pass a generic to useState when the initial value doesn't show the full type.

14. How do you type an Express handler?

import type { Request, Response } from "express";

type Params = { id: string };
type Body = { title: string };

app.put("/courses/:id", (req: Request<Params, unknown, Body>, res: Response) => {
  // req.params.id is string, req.body.title is string – but validate the body at run time!
  res.json({ id: req.params.id, title: req.body.title });
});

15. What tsconfig options would you turn on for a new project?

strict (always), noUncheckedIndexedAccess (array and record lookups include undefined), verbatimModuleSyntax or isolatedModules (for esbuild/SWC), noImplicitOverride, and skipLibCheck to keep builds fast.

How to answer well

  • Say what TypeScript guarantees and what it doesn't – compile time only.
  • Prefer narrowing and unknown over as casts and any, and say why.
  • Show you derive types (utility types, typeof, schemas) instead of duplicating them.

Practice

Try it yourself

  1. A classic live-coding task: type a debounce function so the debounced version keeps the original argument types.

    Show solution
    function debounce<A extends unknown[]>(fn: (...args: A) => void, ms: number): (...args: A) => void {
      let timer: ReturnType<typeof setTimeout> | undefined;
      return (...args: A) => {
        clearTimeout(timer);
        timer = setTimeout(() => fn(...args), ms);
      };
    }
    
    const search = debounce((query: string, page: number) => console.log(`search "${query}" page ${page}`), 50);
    search("ty", 1);
    search("type", 1);
    search("typescript", 2);      // only this call runs
    // search(42);                // error: number is not assignable to string

    Output

    search "typescript" page 2

Quick check

Can an API response typed as User be trusted at run time?

No – types are erased. Validate it with a schema.

Is TypeScript nominally or structurally typed?

Structurally – shape matters, not names.

Which type forces you to check before use: any or unknown?

unknown.

Summary

  • Know the guarantees: compile-time types, erased at run time, structural compatibility.
  • Be fluent with narrowing, generics with constraints and the utility types.
  • For senior roles: conditional types and infer, satisfies, .d.ts files, and typing React and Express.

Practise more on our React interview questions and Next.js interview questions.

Finished this lesson?

Mark it complete to track your progress. You have reached the end of this track — well done!

Popular