ClassDecorator în TypeScript

Tipul unui decorator de clasă în stilul vechi (experimentalDecorators): primește constructorul clasei.

Sintaxă
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

Ce face ClassDecorator

ClassDecorator descrie o funcție care primește constructorul clasei decorate și poate returna un constructor nou care îl înlocuiește (sau nimic). Face parte din tipurile pentru decoratorii „experimentali”, folosiți cu opțiunea experimentalDecorators de framework-uri ca Angular, NestJS sau TypeORM.

Un ClassDecorator care folosește doar primul parametru funcționează și cu decoratorii standard din TypeScript 5.0, pentru că un decorator standard de clasă primește tot clasa ca prim argument (al doilea, context, este ignorat). Pentru cod nou, tipul potrivit este ClassDecoratorContext din varianta standard.

Tipurile pentru decoratorii vechi sunt în biblioteca decorators.legacy, inclusă automat. Celelalte sunt MethodDecorator, PropertyDecorator și ParameterDecorator.

Parametri

Parametru Descriere
target Constructorul clasei decorate.

Ce returnează

Un constructor care înlocuiește clasa sau void.

Exemple

Exemplul 1: Decorator care sigilează clasa

Object.seal împiedică adăugarea de proprietăți noi pe constructor și pe prototip: Reflect.set returnează false. Exemplul rulează cu decoratorii standard, fără experimentalDecorators.

const sigilat: ClassDecorator = (target) => {
    Object.seal(target);
    Object.seal(target.prototype);
};

@sigilat
class Catalog {
    clasa = "a X-a";
    medie(note: number[]): number {
        return note.reduce((s, n) => s + n, 0) / note.length;
    }
}

console.log(Object.isSealed(Catalog), Object.isSealed(Catalog.prototype));
console.log(new Catalog().clasa, new Catalog().medie([9, 10]));
console.log("metodă nouă adăugată:", Reflect.set(Catalog.prototype, "sterge", () => {}));

Rezultat

true true
a X-a 9.5
metodă nouă adăugată: false

Exemplul 2: Decorator care înregistrează clasele

const componente: string[] = [];

function componenta(nume: string): ClassDecorator {
    return (target) => {
        componente.push(`${nume} -> ${target.name}`);
    };
}

@componenta("lista-elevi")
class ListaElevi {}

@componenta("formular-nota")
class FormularNota {}

console.log(componente);
console.log(typeof ListaElevi, typeof FormularNota);

Rezultat

[ 'lista-elevi -> ListaElevi', 'formular-nota -> FormularNota' ]
function function

Greșeli frecvente

  • Amesteci decoratori scriși pentru experimentalDecorators cu decoratori standard. Alege o singură variantă pentru proiect.
  • Cu decoratorii standard, decoratorul de clasă rulează înainte de inițializarea câmpurilor statice; cu experimentalDecorators, după. Un decorator care sigilează clasa face ca un static camp = ... să arunce TypeError: Cannot define property …, object is not extensible în varianta standard.
  • Returnezi din decorator o clasă care nu extinde clasa originală. Tipul și comportamentul nu mai corespund; returnează class extends target sau nimic.

Comenzi înrudite

  • decoratori: Funcții puse cu @ deasupra claselor, metodelor sau câmpurilor, care le modifică sau le înlocuiesc comportamentul.
  • MethodDecorator: Tipurile decoratorilor vechi pentru metode, proprietăți și parametri, folosite cu experimentalDecorators.
  • class: Clasele din JavaScript, cu tipuri pe câmpuri, constructor și metode, plus modificatori de acces și interfețe.