DEV Community

Paulo Messias
Paulo Messias

Posted on

Type or Interface? When to Use Each and Why

In TypeScript, both type and interface are used to define the shape and behavior of objects, but knowing when to use one over the other can make a big difference in code readability and maintainability. In this post, we'll explore when it's more appropriate to use type or interface, with practical examples and clear guidelines.

1. Defining Object Shapes

When to Use interface

  • Use interface when you need to define the structure of an object or when you want to define contracts that can be implemented by classes.

Example:

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

const user: User = {
  name: "Alice",
  age: 25,
};
Enter fullscreen mode Exit fullscreen mode

Why use interface here?

  • interface is ideal for representing objects, especially when you need something that can be extended or implemented by classes.

When to Use type

  • Use type when you need more flexibility, such as creating complex types, unions, or intersections.

Example:

type User = {
  name: string;
  age: number;
};
Enter fullscreen mode Exit fullscreen mode

Why use type here?

  • While both type and interface can define object shapes, type is preferable if you need to combine types later (e.g., in unions or intersections).

2. Extending Objects

When to Use interface

  • Use interface if you need to extend an object type multiple times, especially in large projects.

Example:

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

interface Admin extends User {
  role: string;
}

const admin: Admin = {
  name: "Bob",
  age: 30,
  role: "Administrator",
};
Enter fullscreen mode Exit fullscreen mode

Why use interface here?

  • The extends syntax in interfaces is clear and intuitive, making it easier to read and maintain code.

When to Use type

  • Use type to combine types using intersections (&) in cases where you don't need direct inheritance.

Example:

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

type Admin = User & {
  role: string;
};

const admin: Admin = {
  name: "Bob",
  age: 30,
  role: "Administrator",
};
Enter fullscreen mode Exit fullscreen mode

Why use type here?

  • type is ideal for explicitly combining types, especially in complex types.

3. Merging Definitions

When to Use interface

  • Use interface if you need to automatically merge type definitions, such as when working with third-party libraries or defining contracts in a large system.

Example:

interface User {
  name: string;
}

interface User {
  age: number;
}

const user: User = {
  name: "Alice",
  age: 30,
};
Enter fullscreen mode Exit fullscreen mode

Why use interface here?

  • With interface, TypeScript automatically merges definitions, which can be useful when working with modules and libraries that may extend already-defined types.

When to Use type

  • Avoid using type if you need automatic merging, as TypeScript does not allow merging type definitions.

Example (not allowed):

type User = {
  name: string;
};

type User = {
  age: number;
}; // Error: Duplicate identifier 'User'.
Enter fullscreen mode Exit fullscreen mode

Why not use type here?

  • type does not support merging, making it less flexible for scenarios where you need to extend or complement type definitions.

4. Classes and Implementations

When to Use interface

  • Use interface when defining contracts for classes, especially in object-oriented programming scenarios.

Example:

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

class Person implements User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
Enter fullscreen mode Exit fullscreen mode

Why use interface here?

  • interface is the natural choice for defining what a class should implement, maintaining compatibility with object-oriented programming patterns.

When to Use type

  • Avoid using type to implement classes, as interface is more intuitive and better supported for this purpose.

Example (not common):

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

class Person implements User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
Enter fullscreen mode Exit fullscreen mode

Why not use type here?

  • interface is designed for implementation contracts, while type is better suited for more complex types, not necessarily for class contracts.

5. Complex Types: Unions and Intersections

When to Use type

  • Use type to create complex types, such as unions and intersections, where interface does not offer support.

Example with Unions:

type Status = "success" | "error" | "loading";

const currentStatus: Status = "success";
Enter fullscreen mode Exit fullscreen mode

Example with Intersections:

type Response = {
  message: string;
};

type Error = {
  code: number;
};

type APIResponse = Response & Error;

const apiResponse: APIResponse = {
  message: "Not Found",
  code: 404,
};
Enter fullscreen mode Exit fullscreen mode

Why use type here?

  • type is extremely powerful for creating composite and dynamic types, allowing combinations that interface cannot handle.

Summary: When to Use type or interface

  • Use interface:

    • To define object structures and when you expect the object to be extended or implemented by classes.
    • When you need automatic definition merging.
    • When defining class contracts.
  • Use type:

    • For unions, intersections, and more complex types.
    • When you need flexibility to create dynamic types.
    • When you want to explicitly combine types.

By understanding these contexts and differences, you can make more informed decisions about when to use type or interface in TypeScript, resulting in cleaner, more robust, and maintainable code.

These are just suggestions, so feel free to share your thoughts in the comments!

Top comments (2)

Collapse
 
jakecarpenter profile image
Jake Carpenter

Great post! I saw a lot of advice to “just pick one and be consistent” when I first started with TS. You’ve very clearly presented the strengths of both, though.

I think this is going to be saved as my go-to reference when some asks me or I’m onboarding first-time TS devs to a project.

Collapse
 
paulocappa profile image
Paulo Messias

I really appreciate that!