TypeScript Tutorial
TypeScript Inheritance
A derived class reuses a base class. Write the shared parts once, then specialize. Use extends and super.
Write the shared parts once
A dog is an animal. A car is a vehicle. In TypeScript that sentence is a type relationship: the derived class gets the members of the base class, then adds or changes what is special.
You list the base after extends: class Dog extends Animal. That is public inheritance in C++ terms — the usual choice for “is-a”. Call the base constructor with super.
class Dog extends Animal
Animal has eat. Dog does not rewrite it. A Dog object can call eat because it inherited the method. It also has bark, which only dogs have.
Example
class Animal {
public eat(): void {
console.log("eating");
}
}
class Dog extends Animal {
public bark(): void {
console.log("woof");
}
}
const d: Dog = new Dog();
d.eat();
d.bark();d.eat() runs the function defined on Animal. You did not copy it intoDog.
Call the base with super
Inside a derived method you can call the base version with super.eat(). That is useful when the derived class wants the shared work plus extra steps. super is the base object inside the derived method.
Example
class Animal {
public eat(): void {
console.log("chewing");
}
}
class Dog extends Animal {
public override eat(): void {
super.eat();
console.log("then wags tail");
}
}
const d: Dog = new Dog();
d.eat();override tells the compiler you mean to replace a base method. A typo in the name then fails at compile time. Without super.eat(), writing this.eat() inside Dog.eatwould call itself and recurse until the program crashed. Name the base when you mean the base.
Derived classes add their own members
Inheritance is not only methods. The derived class can add fields. Keep those fields private on the derived class the same way you would on any class.
Example
class Animal {
public sleep(): void {
console.log("asleep");
}
}
class Dog extends Animal {
private breed: string;
constructor(b: string) {
super();
this.breed = b;
}
public show(): void {
console.log(this.breed);
this.sleep();
}
}
const d: Dog = new Dog("Beagle");
d.show();When the derived class has a constructor, its first statement must be super(...) if the base expects to be constructed. Even a base with no parameters is started with a bare super().
What the derived class can see
| Base member | In a derived class |
|---|---|
| public | Still public. Callers can use it on the derived object. |
| protected | Visible to the derived class, not to outside code. |
| private | Not visible to the derived class. Use a public or protected base method instead. |
Dog cannot read a private field of Animal directly. If the base needs to share a value with children only, mark it protected. Prefer private plus a method when you can.
Construct the base first
When you create a Dog, TypeScript constructs the Animal part first. If the base has a constructor that takes arguments, pass them to super.
Example
class Animal {
private name: string;
constructor(n: string) {
this.name = n;
}
public getName(): string {
return this.name;
}
}
class Dog extends Animal {
constructor(n: string) {
super(n);
}
public speak(): void {
console.log(this.getName() + " says woof");
}
}
const d: Dog = new Dog("Rex");
d.speak();super(n) forwards the name to the base. getName is a public method onAnimal, so Dog can call it. this.name inside Dog would not compile: name is private on the base.
Use inheritance for is-a
- A dog is an animal. Inherit with
extends. - A car has an engine. Prefer a member, not inheritance.
Click Try it in TypeScript under an example to compile it at /typescript/try. That editor is not the Python page at /try. Next: the same animal types, but one function that works on all of them — polymorphism.