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

TypeScript Interfaces vs Types: When to Use Which

Published 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!

Frontend Strategy

Need a frontend roadmap that supports growth, not churn?

I help product and marketing teams simplify stack decisions, reduce frontend drag, and ship faster without creating long-term maintenance debt.

S

Written by Salman Izhar

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

Learn More