TypeScript how does the “Implements” keyword work?`
Key Concepts of TypeScript Interfaces and implements
- Interface as a Contract:
- An interface in TypeScript defines a contract that any implementing class must adhere to.
- It specifies a set of methods and properties without providing implementations.
- Interfaces ensure that classes provide certain behaviors, but they don’t limit classes to only those behaviors.
- Concrete Implementation:
- A class uses the implements keyword to declare that it satisfies the contract defined by an interface.
- The class must provide concrete implementations for all the methods and properties defined in the interface.
- It can also have additional methods and properties that are not part of the interface.
- TypeScript's Structural Typing:
- TypeScript uses structural typing (or "duck typing"), meaning an object satisfies an interface if it has all the required properties and methods.
- A class can have more properties and methods than those defined in the interface, and TypeScript will not raise an error.
- This allows for flexibility and extensibility, enabling classes to offer additional functionality without breaking the interface contract.
- Dependency Injection and Abstraction:
- By relying on interfaces, classes can be more easily decoupled from specific implementations, promoting abstraction.
- Dependency injection allows classes to be initialized with specific implementations that adhere to an interface, enabling flexible design patterns like Clean Architecture.
- This design ensures that business logic can work with any class implementing the interface, providing ease of testing and flexibility.
interface CharacterRepository {
getCharacters(page: number): Promise<Character[]>;
updateCharacter(characterId: string, updatedData: Partial<Character>): Promise<Character>;
}class CharacterRelayRepository implements CharacterRepository {
async getCharacters(page: number): Promise<Character[]> {
// Implementation of fetching characters
}
async updateCharacter(characterId: string, updatedData: Partial<Character>): Promise<Character> {
// Implementation of updating a character
}
async deleteCharacter(characterId: string): Promise<boolean> {
// Additional method not required by the interface
}
}
class GetCharacterList {
private characterRepository: CharacterRepository;
constructor(characterRepository: CharacterRepository) {
this.characterRepository = characterRepository;
}
async execute(page: number): Promise<Character[]> {
return this.characterRepository.getCharacters(page);
}
}
Practical Benefits
- Flexibility:
- You can change or extend the implementation details without modifying the code that depends on the interface.
- Testability:
- Interfaces allow for easy mocking in tests, as you can create mock classes implementing the interface without changing the test setup.
- Separation of Concerns:
- Interfaces allow business logic to be independent of specific data sources or implementations, adhering to the Dependency Inversion Principle.
- Polymorphism:
- Multiple classes can implement the same interface, enabling polymorphism. You can treat instances of different classes as instances of the interface type.
Example for Clarity
Consider a scenario where you have a Vehicle interface and multiple classes implementing it:
interface Vehicle {
drive(): void;
stop(): void;
}
class Car implements Vehicle {
drive() {
console.log("Car driving");
}
stop() {
console.log("Car stopped");
}
honk() {
console.log("Car honking");
}
}
class Bike implements Vehicle {
drive() {
console.log("Bike driving");
}
stop() {
console.log("Bike stopped");
}
}
function testDrive(vehicle: Vehicle) {
vehicle.drive();
vehicle.stop();
}
const myCar = new Car();
const myBike = new Bike();
testDrive(myCar); // Car driving, Car stopped
testDrive(myBike); // Bike driving, Bike stopped
Explanation:
- Interface Definition: Vehicle specifies that implementing classes must have drive and stop methods.
- Concrete Implementations: Both Car and Bike implement Vehicle, providing specific implementations for drive and stop.
- Additional Methods: Car has an additional method honk, which doesn't affect its conformance to the Vehicle interface.
- Usage: The testDrive function can operate on any Vehicletype object, demonstrating polymorphism and the flexibility of using interfaces.
