Skip to Content
Course content

19: Interfaces vs Type Aliases

Click on the "Edit" button in the top corner of the screen to edit your slide content.

They both seem to do the same thing for objects—does it actually matter which one I pick?

If you're just defining the shape of a simple object, honestly? No, it doesn't matter much. You can use interface or type and the code will behave exactly the same way. But as you start building larger systems, the intent changes.

I tend to think of an interface as a "contract." It defines a blueprint for what an object should look like. A type alias, on the other hand, is exactly what it sounds like: an alias. It's just a nickname for any type definition, whether that's an object, a primitive, or a complex union.

// This is a contract. I'm saying "any object that claims to be a User must have these"
interface User {
  id: string;
  username: string;
}

// This is an alias. I'm saying "whenever I say 'UserID', I actually mean a string"
type UserID = string;

// You can also use type for the object shape, and it works fine
type UserAccount = {
  id: UserID;
  email: string;
};


I keep hearing about "declaration merging." Why is that useful?

This is one of the biggest technical differences. Interfaces are "open," meaning if you declare the same interface twice, TypeScript automatically merges them into one. Types are "closed"—once you define a type, you can't just add more properties to it later by declaring it again.

You won't use this every day, but it's a lifesaver when you're working with third-party libraries. Imagine you're using a library that defines a Window interface, but you've added a custom analytics object to the global window in your project. You can't edit the library's code, but you can "reopen" the interface in your own file:

// The library defines this
interface Window {
  localStorage: Storage;
}

// I can "merge" my own property into it without touching the library
interface Window {
  myCustomAnalytics: (event: string) => void;
}

// Now TS knows both properties exist on window
window.myCustomAnalytics('page_view');


Can I do everything with an interface?

Nope. This is where type aliases really shine. Interfaces are limited to describing object shapes. Types can describe anything. The most common scenario where you'll need a type is for Union Types—when a value could be one of several different things.

If you're building a payment system, you might have a status that can only be a few specific strings. You can't do that with an interface.

// This is impossible with an interface
type PaymentStatus = 'pending' | 'completed' | 'failed' | 'refunded';

interface Order {
  id: string;
  status: PaymentStatus; // Using the type alias here
}

const myOrder: Order = {
  id: 'ord_123',
  status: 'completed' // TS will error if I type 'shipped'
};

I usually follow a simple rule of thumb: start with interface for your object structures and data models. The moment you need a union, a tuple, or a primitive alias, switch to type.




📋 Practical Task

Refactoring the E-Commerce Product Schema

You are working on a product catalog. Currently, the developer used type for everything, but the codebase is growing. Your goal is to refactor the code to use interface for the object blueprints and type for the specific constraints.

Requirements:

  • Change the Product definition from a type to an interface.
  • Create a type alias called ProductCategory that is a union of: 'Electronics', 'Clothing', and 'Home'.
  • Update the Product interface to use ProductCategory for its category property.
  • Demonstrate declaration merging by creating a second Product interface declaration that adds an optional discountPrice property (number).

Your final code should allow a product object to have an id, name, category (restricted to the union), and the merged discountPrice.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.