Types vs. Interfaces: Understanding the Differences in TypeScript

@rnab
3 min readOct 30, 2024

--

In the dynamic world of TypeScript, one debate continues to spark conversations among developers — should you use types or interfaces for defining shapes of objects? Despite their similarities, these two constructs have distinct differences and specific use cases that can impact your codebase elegantly if used appropriately.

This article aims to clarify these distinctions with practical examples to equip you with a better understanding of both types and interfaces in TypeScript.

What are Types?

Types in TypeScript offer an essential feature called type aliases. These aliases define a name for a specific type which makes complex type declarations more digestible and manageable.

Usage Patterns

Types are particularly useful when dealing with unions and intersections.

Using Union Types

Union types allow us to declare a variable that can be one of several types:

type Status = 'success' | 'error' | 'loading';
function printStatus(status: Status): void {
console.log(`The current status is ${status}`);
}
printStatus('success'); // The current status is success

Here, Status can be any of the specified string literals.

Intersection Types

Intersection types combine multiple types into one, allowing properties from different types to coalesce into a new type.

type User = {
id: number;
username: string;
};
type Admin = User & {
adminPermissions: boolean;
};
const adminUser: Admin = {
id: 1,
username: "admin123",
adminPermissions: true
};

In this example, we merged the User type with additional Admin properties to create a comprehensive admin user type.

Typing Functions and Complex Types

Type aliases also shine for typing functions and sophisticated data structures seamlessly.

type Callback = (message: string) => void;
const logMessage: Callback = (msg) => {
console.log(msg);
};
logMessage("Hello, Types!");

With this declaration, Callback becomes reusable across different function implementations requiring the same signature.

What are Interfaces?

Interfaces serve as a robust way to enforce contracts in TypeScript by providing an explicit structure to follow. They primarily describe the shape of objects but come with features like interface extension and implementation.

Use Cases for Interfaces

Basic Interface Declaration

Declared using the interface keyword, they eloquently dictate object structure.

interface Vehicle {
make: string;
model: string;
year: number;
}
let myCar: Vehicle = {
make: 'Toyota',
model: 'Corolla',
year: 2020
};

Any object adhering to the Vehicle interface must contain the specified properties and types.

Extending Interfaces

One powerful aspect is extending, where interfaces inherit other interfaces’ members, facilitating a form of prototype-based inheritance.

interface NewVehicle extends Vehicle {
color: string;
}
let updatedCar: NewVehicle = {
make: 'Honda',
model: 'Civic',
year: 2022,
color: 'red'
};

With this setup, NewVehicle carries all attributes of Vehicle along with additional ones.

Implementing Interfaces in Classes

Integrating interfaces with classes allows for consistent enforcement of structure within class instances.

interface Flyable {
fly(): void;
}
class Bird implements Flyable {
fly() {
console.log("I am flying!");
}
}
const eagle = new Bird();
eagle.fly(); // I am flying!

Our Bird class complies with the Flyable contract, ensuring reliable method availability.

Key Differences Between Types and Interfaces

While interchangeable in numerous scenarios, they showcase unique strengths under certain conditions.

Extensibility:

  • Interfaces excel at easy extensions via the extends keyword.
  • Types achieve similar results through intersection types (& operator).

Capabilities:

  • Types handle advanced configurations such as union and tuple types efficiently.
  • Interfaces may be augmented and merged seamlessly across definitions improving modularity.

Declaration Merging:

  • Only interfaces support declaration merging wherein multiple identical named interfaces get combined into a single definition shared across the codebase.

For instance:

interface Box {
height: number;
}
interface Box {
width: number;
}
const package: Box = { height: 5, width: 10 }; // Merges both interfaces implicitly

Conclusion

Both types and interfaces fulfill pivotal roles within TypeScript arrays. Choosing between them often boils down to context-specific needs rather than applying universal rules. Utilize types for advanced compositions like unions/intersections and succinct expressions while adopting interfaces for straightforward, extendable object modeling.

Balancing judiciously between the two not only enriches your TypeScript proficiency but also ensures maintainable, robust, and scalable applications. So go ahead, pick wisely and empower your next project with optimal structural integrity!

--

--

@rnab
@rnab

Written by @rnab

Typescript, Devops, Kubernetes, AWS, AI/ML, Algo Trading

No responses yet