TypeScript Interfaces vs Types: When to Use Which
TypeScriptBest PracticesWeb Development

TypeScript Interfaces vs Types: When to Use Which

January 25, 2025
8 min read
Salman Izhar

TypeScript Interfaces vs Types: The Complete Guide

One of the most common questions TypeScript developers face: "Should I use an interface or a type?" Let's break down the differences.

What Are Interfaces?

Interfaces define the shape of an object, designed for object-oriented programming.

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

const user: User = {
  id: 1,
  name: "John Doe",
  email: "john@example.com"
};

What Are Type Aliases?

Type aliases can represent any type: primitives, unions, intersections, tuples, and objects.

type User = {
  id: number;
  name: string;
};

// Also represents other types
type ID = string | number;
type Callback = (data: string) => void;

Key Differences

1. Declaration Merging

Interfaces support declaration merging - declare the same interface multiple times.
interface Window {
  title: string;
}

interface Window {
  ts: TypeScriptAPI;
}
// Result: Window has both properties
Types cannot be merged.

2. Extending vs Intersection

Interfaces use extends:
interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}
Types use intersections (&):
type Animal = { name: string };
type Dog = Animal & { breed: string };

3. Union Types

Types can represent unions, interfaces cannot:
type Status = "pending" | "approved" | "rejected";
type ID = string | number;

When to Use What?

Use Interfaces:

  • Defining object shapes for classes
  • Need declaration merging
  • Building public APIs

Use Types:

  • Unions or intersections
  • Utility types
  • Primitive aliases or tuples

Real-World Example

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

type ApiResponse = 
  | { status: "success"; data: T }
  | { status: "error"; error: string };

type UserResponse = ApiResponse;

// React Component
interface BaseButtonProps {
  children: React.ReactNode;
  onClick: () => void;
}

type ButtonVariant = "primary" | "secondary";

type ButtonProps = BaseButtonProps & {
  variant?: ButtonVariant;
};

Conclusion

  • Interfaces: Object shapes, class contracts
  • Types: Unions, primitives, transformations

Default to interfaces for objects, use types for everything else!

Get More Like This

Want articles like this in your inbox?

Join developers and founders who get practical insights on frontend, SaaS, and building better products.

S

Written by Salman Izhar

Frontend Developer specializing in React, Next.js, and building high-converting web applications.

Learn More