Type vs Interface in TypeScript: What’s the Difference and When to Use Each?

If you’re building a large-scale TypeScript project or just defining a simple data model, you’ll inevitably face this question:

Should I use a type or an interface?

Let’s break it down in a way that even a sleepy Monday brain can understand β€” with visuals and code!

🎯 What Are They?

Both type and interface let you define the shape of objects in TypeScript.

// Using interface
interface User {
  name: string;
  age: number;
}

// Using type
type User = {
  name: string;
  age: number;
};

πŸ” Result? Same thing! But they behave differently when you start scaling your app.

πŸ” Key Differences (With Visuals)

 

1. Extending Types

interface Admin extends User {
  role: string;
}

type Admin = User & { role: string };

βœ… Both work. But…

 

2. Declaration Merging

 

interface Button {
  label: string;
}

interface Button {
  onClick: () => void;
}

βœ… Interface gets merged into:

// Final Button
interface Button {
  label: string;
  onClick: () => void;
}

❌ type cannot do this. You’ll get a duplicate identifier error.

πŸ“Œ Use Case: Interfaces are great for public APIs and library definitions that evolve over time.

3. Unions and Tuples

type Status = "success" | "error" | "loading";
type Point = [number, number];

βœ… Only type supports union, intersection, tuples, primitives, and template literals.

❌ interface doesn’t support those.

🧩 Visual Summary

Feature interface βœ… type βœ…
Object Shape βœ… βœ…
Extend Another βœ… (extends) βœ… (&)
Declaration Merging βœ… ❌
Union / Intersection Types ❌ βœ…
Tuples / Primitives ❌ βœ…

πŸ› οΈ When to Use Which?

Scenario Use interface Use type
Defining a React component’s props βœ… Yes βœ… Also works
Library or shared API models βœ… Yes ❌ Avoid
Unions, intersections, and utility types ❌ βœ… Yes
Working with tuples, strings, or numbers ❌ βœ… Yes
You want to extend multiple object shapes βœ… Yes βœ… Yes

 

πŸ’‘ Real-World Example

// Using interface for React props
interface ButtonProps {
  label: string;
  onClick: () => void;
}

const Button = ({ label, onClick }: ButtonProps) => (
  <button onClick={onClick}>{label}</button>
);

// Using type for API response status
type Status = "idle" | "loading" | "error" | "success";

🧠 TL;DR

  • βœ… Use interface for object shapes and when working in OOP-style systems or public APIs.

  • βœ… Use type when you need unions, primitives, tuples, or complex compositions.

Leave a Reply

Your email address will not be published. Required fields are marked *