TypeScript: Interfaces vs Types — What to Choose in 2024?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: The Eternal Debate of TypeScript Developers



If you've ever written in TypeScript, you've surely encountered the question: "When should I use interface, and when should I use type?" This question has gathered thousands of views on Stack Overflow and has become a real stumbling block for beginners. Let's finally sort out this dilemma once and for all.



TypeScript is a superset of JavaScript that adds static typing. And we have two main tools for describing data structures: Interface and Type Alias. At first glance, they do the same thing, but the devil is in the details. In this article, we won't just list the differences — we'll show them with real examples and give clear recommendations.



What is an Interface?



An Interface is a way to describe the structure of an object. It's like a blueprint for data: you tell TypeScript what properties and methods an object should have.



// Basic interfaceinterface User {    name: string;    age: number;    email?: string; // optional property    readonly id: number; // read-only}

// Usageconst user: User = { name: "Anna", age: 25, id: 1};


Interfaces can inherit from each other, making them ideal for describing hierarchies:



interface Animal {    name: string;    sound(): void;}

interface Dog extends Animal { breed: string; wagTail(): void;}

// Now Dog contains all Animal fields + its ownconst myDog: Dog = { name: "Rex", breed: "Shepherd", sound() { console.log("Woof!"); }, wagTail() { console.log("Wags tail"); }};


What is a Type Alias?



A Type Alias is a more flexible tool. It can describe not only objects but also primitives, unions, and intersections of types.



// Type for a primitivetype ID = string | number;

// Type for an objecttype UserType = { name: string; age: number;};

// Type for a functiontype Greeting = (name: string) => string;

// Union Typetype Status = "active" | "inactive" | "pending";

// Intersection Typetype Person = { name: string };type Employee = Person & { salary: number };


The main superpower of types is union types. Interfaces can't do that:



// ❌ This is not possible with interface// interface Status = "active" | "inactive"; // Error!

// ✅ But with type it's easy!type Status = "active" | "inactive" | "pending";

function processStatus(status: Status) { switch (status) { case "active": console.log("Active"); break; case "inactive": console.log("Inactive"); break; case "pending": console.log("Pending"); break; }}


Key Differences: Interface vs Type



Let's break down how they differ in practice.



1. Union and Intersection Types

Type supports union (|) and intersection (&) directly. Interface only through extends.



// Union — only typetype Success = { data: string };type Error = { error: string };type Result = Success | Error; // Possible!

// Intersectiontype Full = Success & Error; // Possible!

// For interface, you'd have to create separate interfacesinterface IResult extends Success, Error {} // Works, but is cumbersome


2. Declaration Merging

This is a unique feature of interfaces. If you declare two interfaces with the same name, TypeScript will merge them.



// First interfaceinterface User {    name: string;}

// Second interface with the same nameinterface User { age: number;}

// Result: User = { name: string; age: number; }const user: User = {

Blogs

Book Recommendations