An interface can be thought of as a blueprint for an object or a class, specifying the properties and methods that must be implemented.
What are Interfaces ๐คโ
Interfaces in TypeScript are a powerful way to define contracts within your code, which help to ensure that the structure and types of objects or classes are consistent across your application. They are used to define the shape and properties of an object or a class, and to enforce the implementation of certain methods in a class.
An interface can be thought of as a blueprint for an object or a class, specifying the properties and methods that must be implemented. When an object or a class implements an interface, it must provide a concrete implementation of all the properties and methods defined in the interface.
Interfaces can be used for various purposes in TypeScript, such as:
Defining the shape of an object: Interfaces can be used to define the structure of an object, ensuring that it has specific properties with the appropriate types. This can be useful when working with objects that are expected to adhere to a specific structure throughout the application.
Enforcing implementation of certain methods in a class: Interfaces can be used to specify methods that a class must implement. This is useful when creating a group of classes that should have a consistent set of methods, such as implementing a particular design pattern.
Extending interfaces: Interfaces can extend other interfaces, allowing you to create more complex and specific contracts for your code.
Here's an example of an interface in TypeScript:
Let us assume that we need to have a class that generates a Car object which has a make, model, and year properties like so:
const car = {
make: "Toyota",
model: "Camry",
year: 2022,
};
In this example, the Vehicle
interface defines a contract that includes three
properties (make
, model
, and year
) and two methods (startEngine
and stopEngine
). The Car
class implements the Vehicle
interface, ensuring
that it provides concrete implementations for all the properties and methods
specified in the interface.
interface Vehicle {
make: string;
model: string;
year: number;
startEngine(): void;
stopEngine(): void;
}
class Car implements Vehicle {
constructor(public make: string, public model: string, public year: number) {}
startEngine(): void {
console.log("Engine started.");
}
stopEngine(): void {
console.log("Engine stopped.");
}
}
The make
, model
, and year
properties are defined directly in the
constructor
using the public
access modifier. This simplifies the class definition, as
there
is no need to explicitly declare the properties separately and then assign them
within the constructor.
Time To Transition From JavaScript To TypeScript
Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.
SEE COURSE DETAILSInheritance With Interfacesโ
One of the biggest advantages of using interfaces in TypeScript is that they allow for a flexible and scalable way to define contracts for multiple classes. This is achieved through the following features:
Single interface, single classโ
The concept of single interface, single class refers to the scenario where an interface is implemented by only one class. This approach might be less common compared to using a single interface with multiple classes, but it can still provide benefits in terms of code organization and maintainability.
When you have a single interface implemented by a single class, the interface
still acts as a contract, specifying the required properties and methods that
the class must implement. This ensures that the class adheres to a specific
structure and behavior. What we looked in the above code was an example of
Single interface that is Vehicle
implemented by a single class Car
.
Single interface, multiple classesโ
A single interface can be implemented by multiple classes. This ensures that all the classes that implement the interface follow the same contract, providing a consistent structure and behavior throughout the application. This is especially helpful when dealing with a group of related classes that should have common properties and methods.
Multiple interfaces, single classโ
A class can implement multiple interfaces, allowing it to inherit properties and methods from more than one interface. This provides a level of flexibility that is not possible with single inheritance in classical object-oriented programming. By implementing multiple interfaces, a class can be a part of several different contracts, which makes the code more modular and easier to maintain.
These features enable a high degree of code reusability, consistency, and modularity, which are essential in developing scalable and maintainable applications.
Example: Single interface, multiple classesโ
Let's create another class called Motorcycle
that also implements
the Vehicle
interface, illustrating that the interface can be used for
multiple classes with similar properties and methods. Here's the updated code:
class Motorcycle implements Vehicle {
constructor(public make: string, public model: string, public year: number) {}
startEngine(): void {
console.log("Motorcycle engine started.");
}
stopEngine(): void {
console.log("Motorcycle engine stopped.");
}
}
const myMotorcycle = new Motorcycle("Honda", "CBR600RR", 2021);
console.log(myMotorcycle);
In this example, we added a Motorcycle
class that also implements
the Vehicle
interface. Both the Car
and Motorcycle
classes have the
properties make
, model
, and year
, as well as the methods startEngine
and stopEngine
.
The console output would look like this:
Motorcycle {
make: 'Honda',
model: 'CBR600RR',
year: 2021
}
Example: Multiple interfaces, single classโ
As shown, the Vehicle
interface is used to create different classes (in this
case, Car
and Motorcycle
) with similar properties and methods, ensuring
consistency and adherence to a specific structure throughout the application.
To demonstrate the concept of multiple interfaces being implemented by a single
class, let's create a new interface called Inspectable
that includes a
method inspect()
. Then, we'll update the Car
class to implement both
the Vehicle
and Inspectable
interfaces:
interface Inspectable {
inspect(): void;
}
class Car implements Vehicle, Inspectable {
constructor(public make: string, public model: string, public year: number) {}
startEngine(): void {
console.log("Engine started.");
}
stopEngine(): void {
console.log("Engine stopped.");
}
inspect(): void {
console.log(`Inspecting ${this.year} ${this.make} ${this.model}.`);
}
}
const myCar = new Car("Toyota", "Camry", 2022);
myCar.inspect();
In this example, we created a new interface called Inspectable
with a single
method inspect()
. We then updated the Car
class to implement both
the Vehicle
and Inspectable
interfaces. This means the Car
class must now
provide implementations for all the properties and methods specified in both
interfaces.
The inspect()
method has been added to the Car
class, and when we create an
instance of Car
and call the inspect()
method, we'll see the following
output in the console:
Inspecting 2022 Toyota Camry.
This example demonstrates how a single class (Car
) can implement multiple
interfaces (Vehicle
and Inspectable
), inheriting properties and methods from
each interface and creating a more versatile and modular class.
What Can You Do Next ๐๐โ
If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for ssoftware developers.