TypeScript Interfaces

Learn how interfaces define object shapes, optional properties, and contracts for cleaner typed code.

TL;DR

  1. 01Describe the shape of objects using interface declarations.
  2. 02Mark properties as optional or readonly when needed.
  3. 03Extend interfaces to reuse and combine type definitions.

Tips

  1. 01Use PascalCase for interface names and skip the old <code>I</code> prefix, since modern TypeScript style avoids it.

Warnings

  1. 01Declaration merging can cause unexpected behavior, so avoid reusing interface names across unrelated files.

Basic Syntax

  • Declare an interface using the interface keyword and a PascalCase name.
    interface User {
      id: number;
      name: string;
    }
  • Use the interface as a type annotation when declaring variables.
    const user: User = { id: 1, name: "Sam" };
  • List each property with its name and type inside curly braces.
  • Add semicolons or commas between properties — both are valid.
  • Group related properties into one interface to describe a single object shape.

Property Modifiers

  • Mark a property as optional using a question mark after its name.
    interface User {
      id: number;
      email?: string;
    }
  • Use the readonly keyword to prevent a property from being changed later.
    interface Point {
      readonly x: number;
      readonly y: number;
    }
  • Combine readonly with optional properties for safe configuration objects.
  • Use index signatures for objects with dynamic keys of the same type.
    interface Scores {
      [name: string]: number;
    }
  • Set required properties without modifiers, since required is the default.

Methods

  • Define methods inside an interface using the shorthand call syntax.
    interface Greeter {
      greet(name: string): string;
    }
  • Add parameter types and return types just like regular function declarations.
  • Use arrow function style with a property and function type.
    interface Greeter {
      greet: (name: string) => string;
    }
  • Both syntax styles work — pick one and stay consistent across your project.
  • Type method overloads by listing multiple call signatures inside the interface.

Extending

  • Extend an interface using the extends keyword to inherit its properties.
    interface Animal {
      name: string;
    }
    interface Dog extends Animal {
      breed: string;
    }
  • Extend multiple interfaces by listing them separated by commas.
    interface Hybrid extends Animal, Trainable {}
  • Override inherited properties by redeclaring them with a more specific type.
  • Use extension to build small base interfaces into larger composed shapes.
  • Merge two interfaces with the same name automatically through declaration merging.

Interface vs Type

  • Use interfaces for object shapes and class contracts in most cases.
    interface User { id: number; name: string }
  • Use type aliases for unions, intersections, primitives, and tuples instead.
    type Status = "loading" | "success" | "error";
  • Only interfaces support declaration merging across multiple files.
  • Both support extension, but interfaces use extends and types use intersections.
  • Pick one style per project to keep your codebase consistent.

FAQ