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.

typescript
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.

typescript
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.
typescript
interface Window {
  title: string;
}

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

2. Extending vs Intersection

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

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

3. Union Types

Types can represent unions, interfaces cannot:
typescript
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

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

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

type UserResponse = ApiResponse<User>;

// 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