Classes vs Interfaces in TypeScript - What's the Difference?
Learn Key Differences Between Classes and Interfaces in TypeScript
Classes and interfaces are fundamental building blocks in TypeScript. While they have some similarities, they serve different purposes. This post explains the key differences between classes and interfaces in TypeScript with examples.
Why Classes and Interfaces Matter in TypeScript
Understanding how classes and interfaces work in TypeScript is important for a few reasons:
Classes allow you to create objects with data and behavior. Interfaces define contracts for what classes must be implemented.
TypeScript's type system relies heavily on classes and interfaces to provide static typing.
Knowing when to use classes versus interfaces will help you write cleaner, more maintainable TypeScript code.
Class Overview
Classes are like blueprints for creating objects in JavaScript. They're great when you want to make something with both data and actions attached to it. Think of them as a way to bundle together the characteristics (data) and behaviors (actions) of something.
Example: Imagine you're building an app, and you want to represent people in it. You can use a class called "Person" to store details like a person's name and age. It's like creating a template for people, where you can also define what they can do, like say hello or introduce themselves.
Class Example
class Person {
// Properties
name: string;
// Constructor
constructor(name: string) {
// Initialize the 'name' property with the provided name.
this.name = name;
}
// Method
sayHello() {
// Display a greeting message including the 'name' property.
console.log(`Hello, my name is ${this.name}`);
}
}
// Create a new Person object with the name "Alice".
const person1 = new Person("Alice");
// Call the 'sayHello' method to introduce the person.
person1.sayHello(); // Outputs: Hello, my name is Alice
Purpose: Classes are used when you want to create instances (objects) of a specific type that have both data and behavior associated with them.
Instance Creation: You can create instances of classes using the
new
keyword.Implementation: Classes contain the implementation of methods and properties.
Inheritance: Classes support inheritance using
extends
.Constructor: Classes can have constructors that run on instantiation.
Access Modifiers: Properties and methods can have modifiers like
public
andprivate
.
Interface Overview
Interfaces are like contracts in JavaScript. They define what something should look like, but they don't provide the actual content. They're perfect when you want to ensure that different parts of your code follow the same structure.
Example: Suppose you have different types of animals in your app, like dogs and cats. You can use an interface called "Animal" to say that every animal should have a name and be able to make a sound. However, the interface doesn't tell you how a specific animal makes a sound; it just says they should be able to do it.
Interface Example
interface Animal {
// Property: Name of the animal.
name: string;
// Method: Make a sound specific to the animal.
makeSound(): void;
}
class Dog implements Animal {
// Property: Name of the dog.
name: string;
// Constructor
constructor(name: string) {
// Initialize the 'name' property with the provided name.
this.name = name;
}
// Implement the 'makeSound' method for a dog.
makeSound() {
// Display a barking sound along with the dog's name.
console.log(`${this.name} barks`);
}
}
// Create a new Dog object named "Buddy."
const myDog = new Dog("Buddy");
// Call the 'makeSound' method to hear the dog bark.
myDog.makeSound(); // Outputs: Buddy barks
Purpose: Interfaces define the structure and contract for classes.
Instance Creation: You cannot instantiate interfaces directly.
Implementation: Interfaces only declare structure, not implementation.
Inheritance: Interfaces support declaration merging.
Constructor: Interfaces cannot have constructors.
Access Modifiers: Interfaces do not have access modifiers.
Comparison of Classes vs. Interfaces
Point | Classes | Interfaces |
Purpose | Instantiate objects | Define contracts for structure |
Instance creation | Use new keyword | Cannot instantiate directly |
Implementation | Contains implementation | Just declarations, no implementation |
Inheritance | Extends classes | Declaration merging |
Constructor | Has constructor | No constructor |
Access modifiers | Has public , private , etc. | No access modifiers |
Optional properties | Not supported | Can mark optional properties with ? |
At Last, this is a bonus learning for you
// Define an interface with an optional property.
interface Person {
name: string;
age?: number; // '?' indicates that 'age' is optional
}
// Create objects conforming to the 'Person' interface.
const person1: Person = { name: "Alice" };
const person2: Person = { name: "Bob", age: 30 };
console.log(person1); // Outputs: { name: 'Alice' }
console.log(person2); // Outputs: { name: 'Bob', age: 30 }
This code demonstrates how you can use the ?
symbol to specify that a property in an interface is optional.
Summary
Classes and interfaces serve different roles in TypeScript. Classes are used to create objects with data and behaviors, while interfaces enforce contracts on structure and behavior. Understanding when to use each will help you leverage types effectively.