RSRobince Studio

TypeScript interview revision notes

Strongly-typed JavaScript for safer, more maintainable code. Written for developers preparing for an interview who want to refresh their TypeScript fast. Free, no sign-up.

10 topics in these notes

  1. What is TypeScript?
  2. Basic types & type annotations
  3. Interfaces & type aliases
  4. Union & intersection types
  5. Functions & generics
  6. Classes & OOP in TypeScript
  7. tsconfig & compiler options
  8. any, unknown, never
  9. Utility types & mapped types
  10. TypeScript with Node & React (high-level)

What is TypeScript?

Simple real-life example (Understand first — very important for understanding)

  • Think of filling a form where each field clearly says what kind of data it expects: number, date, email.
  • If you put the wrong kind of value, you get a warning before the form is even used.
  • TypeScript plays the same role for your JavaScript code.

Real-world idea: TypeScript adds a type-checking "safety net" on top of JavaScript so many bugs are caught while you code, not in production.

Technical definition

  • TypeScript is a superset of JavaScript that adds static typing, interfaces, generics, and modern language features.
  • TS code is compiled (transpiled) down to plain JavaScript that runs anywhere JS runs.
  • Type checking happens at compile time; runtime behavior is still JavaScript.

Simple practical example

You annotate function parameters and return types so the compiler warns you when you call them with wrong arguments or forget to handle a case.

Code example

function add(a: number, b: number): number {
  return a + b;
}

add(1, 2);      // OK
// add(1, '2'); // TS error: '2' is not assignable to number

Why it matters

Strong typing reduces runtime bugs, improves editor autocomplete, and makes large codebases easier to refactor and onboard to.

Interview tip

Explain TypeScript as "JavaScript + types" that compile to JS. Emphasize earlier bug detection, better tooling, and smoother refactors.

Basic types & type annotations

Simple real-life example (Understand first — very important for understanding)

  • Like labeling jars in your kitchen: sugar (string), count (number), isOpen (boolean).
  • Because they’re labeled, you don’t accidentally pour salt where sugar is expected.

Real-world idea: basic types make it clear what kind of value each variable should hold so you don’t misuse it later.

Technical definition

  • Primitive types: string, number, boolean, null, undefined, bigint, symbol.
  • Special types: any, unknown, void, never.
  • You annotate with `: Type` after variable names, parameters, and return types.

Simple practical example

Annotate variables and function signatures so misuse like adding strings to numbers or calling methods that don’t exist is caught at compile time.

Code example

let username: string = 'Robin';
let age: number = 30;
let isActive: boolean = true;

function greet(name: string): void {
  console.log(`Hello, ${name}`);
}

// greet(123); // Error: number not assignable to string

Why it matters

Basic types and annotations are the foundation of TypeScript; everything else builds on them. Interviews often start with these basics.

Interview tip

Be ready to explain any vs unknown vs never vs void and when you’d use each, plus how strictNullChecks affects null/undefined.

Interfaces & type aliases

Simple real-life example (Understand first — very important for understanding)

  • Like defining a standard form for a customer: it must have name, email, and optionally phone.
  • Everyone who handles customers agrees on the same shape.

Real-world idea: interfaces and type aliases describe the shape of objects and data. They are contracts your code agrees to follow.

Technical definition

  • Interface: `interface User { name: string; email: string; }`.
  • Type alias: `type User = { name: string; email: string };`.
  • Interfaces can be extended/merged; type aliases can compose via unions & intersections.

Simple practical example

Define a User type once and reuse it across API responses, components, and functions so changes are centralized.

Code example

interface User {
  id: number;
  name: string;
  email: string;
}

function sendWelcome(user: User) {
  console.log(`Welcome, ${user.name}`);
}

type Id = number | string; // type alias

Why it matters

Consistent shapes reduce bugs and make refactors easier. Most real TS codebases are built heavily on interfaces and aliases.

Interview tip

Know interface vs type alias trade-offs (declaration merging, unions/intersections) and when you’d prefer one over the other.

Union & intersection types

Simple real-life example (Understand first — very important for understanding)

  • Union: "tea OR coffee" — you get one of several options.
  • Intersection: "singer AND guitarist" — you need someone who is both.

Real-world idea: unions model either/or values; intersections model values that must satisfy multiple type requirements at once.

Technical definition

  • Union: `type Result = Success | Error;`.
  • Intersection: `type Employee = Person & { salary: number };`.
  • Discriminated unions use a common `kind` (or similar) field for safe narrowing.

Simple practical example

Model API responses where data can be success or error; use a union and switch on a discriminant field to handle all cases.

Code example

type Success = { status: 'ok'; data: string };
type Failure = { status: 'error'; message: string };

type ApiResponse = Success | Failure;

function handle(res: ApiResponse) {
  if (res.status === 'ok') {
    console.log(res.data);
  } else {
    console.error(res.message);
  }
}

Why it matters

Union and intersection types let you express real-world constraints precisely and avoid `any` everywhere.

Interview tip

Be comfortable showing a discriminated union and explaining how narrowing works with `if` or `switch` on the tag field.

Functions & generics

Simple real-life example (Understand first — very important for understanding)

  • A function that sorts cards doesn’t care if the cards are numbers, names, or custom objects—as long as it knows how to compare them.
  • Generics are like placeholders for types so one function works safely with many kinds of inputs.

Real-world idea: generics let you write functions that are flexible but still type-safe, instead of falling back to any.

Technical definition

  • Generic function: `function identity<T>(value: T): T { return value; }`.
  • You can constrain type parameters: `T extends SomeBase`.
  • Arrow functions and methods can also be generic.

Simple practical example

Use generics for data helpers (e.g. wrap, map, filter) and API clients where the response type can vary but should be checked.

Code example

function identity<T>(value: T): T {
  return value;
}

const n = identity<number>(42);
const s = identity('hello'); // type inferred as string

Why it matters

Generics are central to real-world TS: arrays, promises, React hooks, and many library APIs are generic.

Interview tip

Show a simple generic and explain how it keeps the "input type = output type" relationship without using any.

Classes & OOP in TypeScript

Simple real-life example (Understand first — very important for understanding)

  • Like blueprints for different types of vehicles: Car, Bike, Truck; each has common and specific behavior.
  • You can say "any vehicle that can move" without caring which exact kind it is.

Real-world idea: classes, interfaces, and access modifiers help you model real entities with clear boundaries and reuse logic via inheritance or composition.

Technical definition

  • Classes support fields, constructors, methods, access modifiers (public, private, protected) and readonly.
  • Implements: a class can promise to follow one or more interfaces.
  • Abstract classes define a base with shared behavior and abstract methods for subclasses.

Code example

interface Shape {
  area(): number;
}

class Rectangle implements Shape {
  constructor(public width: number, public height: number) {}
  area(): number { return this.width * this.height; }
}

Why it matters

TS classes and interfaces make OOP patterns explicit and type-checked, which many teams and frameworks rely on.

Interview tip

Explain access modifiers, implements vs extends, and why you might use interfaces instead of concrete classes in some designs.

tsconfig & compiler options

Simple real-life example (Understand first — very important for understanding)

  • Like a control panel for your project: which rules are strict, which features are enabled, and where to output results.
  • You dial up strictness over time to catch more mistakes.

Real-world idea: `tsconfig.json` defines how TS compiles and how strict it is. Small changes here can greatly improve safety.

Technical definition

  • Key options: `target`, `module`, `strict`, `noImplicitAny`, `strictNullChecks`, `outDir`, `rootDir`.
  • Include/exclude control which files are type-checked and emitted.
  • Different configs for app, library, tests via extends or multiple tsconfig files.

Simple practical example

Start from `strict: true` and relax only if needed. Configure `baseUrl` and `paths` for clean module imports in larger projects.

Code example

{
  "compilerOptions": {
    "target": "ES2019",
    "module": "commonjs",
    "strict": true,
    "outDir": "dist",
    "rootDir": "src"
  }
}

Why it matters

Many interview questions touch strict mode and tsconfig. Real projects rely on these settings for consistent builds and safety.

Interview tip

Mention `strict`, `noImplicitAny`, and `strictNullChecks` as must-have options, and explain what they protect you from.

any, unknown, never

Simple real-life example (Understand first — very important for understanding)

  • any: like turning off all checks—user can write anything into any field.
  • unknown: you know something is there, but you must check what it is before using it.
  • never: a situation that cannot happen (or a function that never finishes normally).

Real-world idea: these special types control how much you trust a value and how strict the compiler is about using it.

Technical definition

  • any: opt-out of type checking; can be assigned to/from anything.
  • unknown: top type that must be narrowed before use.
  • never: bottom type—subtype of every type; used for impossible code paths and functions that throw or loop forever.

Simple practical example

Use unknown for values from external sources (e.g. JSON.parse) and validate them; avoid any in new code; never appears in exhaustive checks.

Code example

function fail(message: string): never {
  throw new Error(message);
}

function handle(value: unknown) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase());
  }
  // else branch remains unknown
}

Why it matters

Understanding these types lets you gradually tighten type safety and model edge cases precisely.

Interview tip

Show you know why any is dangerous, how unknown forces narrowing, and where never appears (e.g. exhaustive switch).

Utility types & mapped types

Simple real-life example (Understand first — very important for understanding)

  • Like taking an existing form and marking all fields optional, or picking only a few fields for a short version.
  • You don’t redraw the form from scratch; you transform the existing one.

Real-world idea: utility and mapped types let you transform existing types instead of repeating yourself.

Technical definition

  • Built-in utilities: Partial, Required, Readonly, Pick, Omit, Record, ReturnType, etc.
  • Mapped types: `[K in keyof T]` to create new types based on keys of T.
  • Often combined with conditional types for advanced transformations.

Simple practical example

Create DTOs, patch types, and read-only views of data models without redefining all properties manually.

Code example

interface User {
  id: number;
  name: string;
  email: string;
}

type UserUpdate = Partial<Pick<User, 'name' | 'email'>>;

Why it matters

Utility types are everywhere in real TS projects and libraries. They are a common interview topic for more advanced TS roles.

Interview tip

Know at least Partial, Pick, Omit, Readonly, and Record, and be able to give a short example of each.

TypeScript with Node & React (high-level)

Simple real-life example (Understand first — very important for understanding)

  • Think of TS as a layer of safety around your existing Node or React app: the runtime stays the same, but you get more guardrails.
  • You still ship JS, but the journey there is safer and more predictable.

Real-world idea: you don’t rewrite everything; you gradually add TS types to existing Node/React code, improving safety over time.

Technical definition

  • Node: use ts-node for dev or compile with tsc into a dist folder, then run with node.
  • React: use `create-react-app --template typescript` or Vite/Next templates; use JSX/TSX with typed props and hooks.
  • Types via @types packages (DefinitelyTyped) for many libraries.

Simple practical example

For a Node API, define Request/Response DTOs and use them in route handlers. For React, type component props and hook returns.

Why it matters

Most modern JS backends/frontends at scale are built with TS. Knowing how to wire TS into Node and React is a common expectation.

Interview tip

Be ready to explain at a high level how you’d add TS to an existing JS codebase and how it changes the dev workflow.

More Frontend notes

HTML · CSS · JavaScript · JavaScript in the Browser · React · Angular · All developer notes