extends în TypeScript

Clase TypeScript 1.0

O clasă moștenește câmpurile și metodele altei clase; o interfață preia proprietățile altor interfețe.

Sintaxă
class Copil extends Parinte {
    constructor(...) { super(...); }
}
interface B extends A { ... }

Ce face extends

class Copil extends Parinte creează o clasă care are tot ce are Parinte și poate adăuga câmpuri și metode noi sau poate rescrie metode existente. Dacă clasa derivată are constructor, acesta trebuie să apeleze super(...) înainte de a folosi this. O metodă rescrisă poate apela versiunea părintelui cu super.metoda().

Un obiect al clasei derivate poate fi folosit oriunde se cere clasa de bază. O clasă poate extinde o singură clasă, dar poate implementa oricâte interfețe. La interfețe, extends poate primi mai multe nume: interface C extends A, B.

Același cuvânt are alt sens în generics: <T extends Tip> este o constrângere, iar în tipurile condiționale T extends U ? X : Y este o întrebare. Pentru metodele rescrise vezi și override.

Exemple

Exemplul 1: Moștenire cu super

class Produs {
    constructor(public nume: string, public pret: number) {}
    eticheta(): string {
        return `${this.nume}: ${this.pret.toFixed(2)} lei`;
    }
}

class ProdusRedus extends Produs {
    constructor(nume: string, pret: number, public reducere: number) {
        super(nume, pret);
    }
    override eticheta(): string {
        const nou = this.pret * (1 - this.reducere / 100);
        return `${super.eticheta()} → ${nou.toFixed(2)} lei (-${this.reducere}%)`;
    }
}

const produse: Produs[] = [new Produs("Caiet", 8), new ProdusRedus("Rucsac", 150, 20)];
for (const p of produse) console.log(p.eticheta());

Rezultat

Caiet: 8.00 lei
Rucsac: 150.00 lei → 120.00 lei (-20%)

Exemplul 2: this înainte de super

class Animal {
    constructor(public nume: string) {}
}
class Caine extends Animal {
    rasa: string;
    constructor(nume: string, rasa: string) {
        this.rasa = rasa;
        super(nume);
    }
}
console.log(new Caine("Rex", "ciobănesc"));

Eroarea afișată de tsc

exemplu.mts(7,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.

Exemplul 3: Interfață care extinde mai multe interfețe

interface CuNume {
    nume: string;
}
interface CuOras {
    oras: string;
}
interface Elev extends CuNume, CuOras {
    clasa: string;
}

const e: Elev = { nume: "Ana", oras: "Iași", clasa: "a X-a" };
console.log(`${e.nume}, ${e.clasa}, ${e.oras}`);

Rezultat

Ana, a X-a, Iași

Greșeli frecvente

  • Construiești ierarhii adânci (A extinde B extinde C extinde D). Codul devine greu de urmărit; preferă clase mici și compunerea lor.
  • Rescrii o metodă cu alt tip al parametrilor sau al rezultatului. tsc dă eroare dacă noul tip nu este compatibil cu cel din clasa de bază.

Comenzi înrudite

  • class: Clasele din JavaScript, cu tipuri pe câmpuri, constructor și metode, plus modificatori de acces și interfețe.
  • override: Marchează o metodă care rescrie o metodă din clasa de bază; tsc dă eroare dacă metoda de bază nu există.
  • abstract: O clasă abstract nu poate fi instanțiată; metodele abstract trebuie implementate în clasele derivate.
  • implements: O clasă promite că respectă una sau mai multe interfețe; tsc verifică dacă are toți membrii ceruți.
  • constrângeri generice (extends): T extends Tip limitează tipurile permise pentru T, ca funcția să poată folosi proprietățile lui Tip.