Types vs Interfaces

Both define object shapes. Use interface by default; switch to type when you need unions, intersections, or mapped types.

Quick Comparison

Featureinterfacetype
Object shapeYesYes
Extend/inheritextends& intersection
Declaration mergingYesNo
Union typesNoYes
Mapped typesNoYes
Class implementsYesNo

Interface: Declaration Merging

Interfaces with the same name merge automatically:

interface Point {
  x: number;
}

interface Point {
  y: number;
}

// Point now has both x and y
const p: Point = { x: 1, y: 2 };

This is how libraries extend built-in types (like adding properties to Window).

Type: Unions and Computed Types

Types handle things interfaces can’t:

type Result = "success" | "error" | "pending";  // union of literals
type Callback = (data: string) => void;          // function type
type Pair<T> = [T, T];                           // tuple
type Keys = keyof User;                          // computed from another type

Rule of Thumb

Use interface for object shapes in public APIs (classes, props, configs). Use type for unions, function signatures, and computed types.

// Interface: describes a thing
interface User {
  name: string;
  email: string;
}

// Type: describes a computation or union
type Status = "active" | "inactive";
type UserWithStatus = User & { status: Status };