Part 4: Interfaces and Composition - Contracts and Flexibility
Introduction
The Problem: Rigid Inheritance
// Inheritance-based approach - inflexible
class Logger {
log(message: string): void {
console.log(message);
}
}
class Service extends Logger {
execute(): void {
this.log('Executing service');
}
}
// Problem 1: Can only extend one class
// class Service extends Logger, Database {} // Error!
// Problem 2: Tightly coupled to implementation
// What if we want to log to a file instead of console?
// Problem 3: Cannot test in isolation
// Service always logs to console during testsThe Solution: Interfaces and Composition
TypeScript Interfaces
Basic Interface
Optional Properties
Readonly Properties
Method Signatures
Interface Inheritance
Composition Patterns
Strategy Pattern
Dependency Injection
Real Example: Storage Abstraction
Real Example: Payment Processing
Multiple Interface Implementation
Best Practices
1. Program to Interfaces, Not Implementations
2. Keep Interfaces Small and Focused
3. Use Composition Over Inheritance
4. Dependency Injection for Testability
What's Next
PreviousPart 3: Inheritance and Polymorphism - Code Reuse and FlexibilityNextPart 5: SOLID Principles and Design Patterns - Production-Ready Code
Last updated