extends keyword. TypeScript enforces strict initialization order with super() and prevents silent method typos using the override modifier.1. Class Inheritance with extends#
When a class extends another class, it establishes a prototypal inheritance link. The derived class inherits all public and protected members of the parent class.
// Base Superclass
class UserNotification {
public id: string;
public createdAt: Date = new Date();
constructor(id: string) {
this.id = id;
}
public send(recipient: string): void {
console.log(`[Notification ${this.id}]: Sent to ${recipient}`);
}
}
// Derived Subclass
class EmailNotification extends UserNotification {
// Inherits 'id', 'createdAt', and 'send()' automatically!
public emailSubject: string = "Account Update";
public attachPdf(filename: string) {
console.log(`Attached PDF: ${filename} to Notification ${this.id}`);
}
}
const email = new EmailNotification("notif_9981");
email.attachPdf("statement.pdf");
email.send("alice@acme.com"); // Inherited method from UserNotification!
2. Constructor Chaining with super()#
If a derived subclass defines its own explicit constructor(), it MUST call super() as its first action before accessing this or returning.
The Order of Initialization Rule:#
super(...args)is executed, initializing the base superclass fields and running the parent constructor.- Parameter properties and instance fields of the subclass are initialized.
- The remaining body of the subclass constructor runs.
class BaseComponent {
public elementId: string;
constructor(elementId: string) {
this.elementId = elementId;
console.log(`[1. BaseComponent]: Initialized DOM element #${this.elementId}`);
}
}
class ModalComponent extends BaseComponent {
public isOpen: boolean = false;
constructor(elementId: string, public title: string) {
// ❌ Compiler Error: 'super' must be called before accessing 'this' in the constructor!
// console.log(this.title);
// 🟢 CORRECT: Must call super() FIRST!
super(elementId);
// NOW it is safe to use 'this'
console.log(`[2. ModalComponent]: Initialized Modal "${this.title}"`);
}
}
const modal = new ModalComponent("app-modal", "Delete Account Confirmation");3. Method Overriding & super.method()#
A subclass can override (redefine) a method inherited from its parent class to provide specialized behavior.
If the subclass still wants to execute the parent’s original implementation, it can invoke super.methodName(...).
class BaseRepository {
public save(data: unknown): void {
console.log("[BaseRepo]: Persisting data to SQL database...");
}
}
class CachingRepository extends BaseRepository {
// Overriding save()
public override save(data: unknown): void {
console.log("[CachingRepo]: Evicting Redis cache layer...");
// Delegate physical persistence to parent class using super!
super.save(data);
console.log("[CachingRepo]: Save complete.");
}
}
const repo = new CachingRepository();
repo.save({ id: 101, name: "Order" });Terminal Output:
[CachingRepo]: Evicting Redis cache layer...
[BaseRepo]: Persisting data to SQL database...
[CachingRepo]: Save complete.4. The override Modifier (TypeScript 4.3+)#
Imagine a scenario where a parent class has a method named renderUI(). In a subclass, you override renderUI().
A year later, an engineer renames the parent method to render() during a refactoring.
Without protection, your subclass method renderUI() is no longer an override—it silently becomes a completely new, uncalled method! This leads to massive, unhandled runtime bugs.
To eliminate this vulnerability, TypeScript 4.3 introduced the override keyword (and the "noImplicitOverride": true tsconfig flag):
{
"compilerOptions": {
"noImplicitOverride": true
}
}When "noImplicitOverride": true is enabled, you MUST explicitly add the override keyword to any subclass method intended to override a parent method:
class ParentView {
public render(): void {
console.log("Rendering Parent");
}
}
class ChildView extends ParentView {
// 🟢 Explicit 'override' keyword verifies the parent method exists!
public override render(): void {
console.log("Rendering Child");
}
// ❌ Compiler Error: This member cannot have an 'override' modifier
// because it is not declared in the base class 'ParentView'.
/*
public override renderOld(): void {
console.log("Old Render");
}
*/
}5. Prototypal Inheritance Under the Hood#
In JavaScript’s prototype model, extends configures two prototype pointers:
class Animal {}
class Dog extends Animal {}
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(Dog.__proto__ === Animal); // true (Static inheritance!)
This means static fields and methods are also inherited across extends chains!
Summary & Next Steps#
In this episode:
- We derived subclasses using
extends. - We mastered Constructor Chaining:
super()must be called before accessingthis. - We invoked parent class implementations using
super.methodName(). - We configured
"noImplicitOverride": trueand used theoverridekeyword to prevent silent refactoring bugs.
In Episode 22: Abstract Classes, we will learn how to build non-instantiable base blueprints using abstract class and abstract method signatures!

