Herança em TypeScript
Um dos aspectos fundamentais do paradigma orientado a objetos é a herança. No TypeScript, a herança é implementada por meio da palavra-chave extends (como no Java):
class Person {
  name: string;
  constructor(userName: string) {
    this.name = userName;
  }
  print(): void {
    console.log(`Nome: ${this.name}`);
  }
}
class Employee extends Person {
  company: string;
  work(): void {
    console.log(`${this.name} trabalha na empresa ${this.company}`);
  }
}
let bob: Employee = new Employee("Bob");
bob.print();
bob.company = "Microsoft";
bob.work();A classe Employee, que representa um funcionário, é uma subclasse que herda da classe Person. A classe Person é chamada de classe pai ou classe base. Com a herança, a classe Employee adquire toda a funcionalidade da classe Person, todas as suas propriedades e métodos, podendo usá-los. Além disso, é possível definir na subclasse novas propriedades e métodos que não existem na classe Person.
let bob: Employee = new Employee("Bob");
bob.print();
bob.company = "Microsoft";
bob.work();Sobrescrita do construtor
Se a subclasse define seu próprio construtor, ela deve chamar o construtor da classe base usando a palavra-chave super:
class Person {
  name: string;
  constructor(userName: string) {
    this.name = userName;
  }
  print(): void {
    console.log(`Nome: ${this.name}`);
  }
}
class Employee extends Person {
  company: string;
  constructor(name: string, company: string) {
    super(name);
    this.company = company;
  }
  work(): void {
    console.log(`${this.name} trabalha na empresa ${this.company}`);
  }
}
let bob: Employee = new Employee("Bob", "Microsoft");
bob.work(); // Bob trabalha na empresa MicrosoftUsando a palavra-chave super, a subclasse pode acessar a funcionalidade da classe base. Neste caso, ela chama o construtor da classe Person, que define o valor da propriedade name: super(name).
Mesmo que a classe base não defina explicitamente nenhum construtor, na classe derivada, ao definir um construtor, ainda é necessário chamar o construtor da classe base. Nesse caso, será uma chamada ao construtor padrão usando super().
class Person {
  name: string;
}
class Employee extends Person {
  company: string;
  constructor(name: string, company: string) {
    super(); // chamada ao construtor da classe base
    this.name = name;
    this.company = company;
  }
  work(): void {
    console.log(`${this.name} trabalha na empresa ${this.company}`);
  }
}
let bob: Employee = new Employee("Bob", "Microsoft");
bob.work(); // Bob trabalha na empresa MicrosoftSobrescrita de métodos
As classes derivadas também podem sobrescrever métodos das classes base:
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  print(): void {
    console.log(`Nome: ${this.name}`);
  }
}
class Employee extends Person {
  company: string;
  constructor(name: string, company: string) {
    super(name);
    this.company = company;
  }
  print(): void {
    console.log(`Nome: ${this.name}`);
    console.log(`Trabalha na empresa: ${this.company}`);
  }
}
let bob: Employee = new Employee("Bob", "Microsoft");
bob.print();Neste caso, o método print() é sobrescrito e, além do nome, também exibe a empresa do funcionário. No entanto, nessa situação, a implementação do método print() da classe base é repetida na classe derivada. Em vez de duplicar código, podemos usar a palavra-chave super para chamar a implementação desse método da classe base:
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  print(): void {
    console.log(`Nome: ${this.name}`);
  }
}
class Employee extends Person {
  company: string;
  constructor(name: string, company: string) {
    super(name);
    this.company = company;
  }
  print(): void {
    super.print();
    console.log(`Trabalha na empresa: ${this.company}`);
  }
}
let bob: Employee = new Employee("Bob", "Microsoft");
bob.print();