Decorator in TypeScript

Decorator in TypeScript

Questo articolo spiega i decorator in TypeScript.

YouTube Video

Decorator in TypeScript

I decorator di TypeScript sono un meccanismo per aggiungere funzionalità o comportamenti aggiuntivi a classi, metodi, accessori, proprietà o parametri. I decorator sono uno strumento potente per migliorare la leggibilità e la riusabilità del codice.

Basi dei Decorator

Un decorator è una funzione che inietta funzionalità aggiuntive in una classe o nei membri di una classe. I decorator sono stati introdotti in TypeScript 1.5 e sono stati proposti anche per lo standard ECMAScript.

1{
2  "compilerOptions": {
3    "experimentalDecorators": true
4  }
5}
  • Per usare i decorator, è necessario abilitare l'opzione experimentalDecorators nel file tsconfig.json.

Tipi di Decorator

In TypeScript, puoi usare i seguenti cinque tipi di decorator.

  • Decoratore di Classe Un decoratore applicato a una classe.
  • Decoratore di Metodo Un decoratore applicato a un metodo di una classe.
  • Decoratore di Accessor Un decoratore applicato a un getter o setter di una proprietà di una classe.
  • Decoratore di Proprietà Un decoratore applicato a una proprietà di una classe.
  • Decoratore di Parametro Un decoratore applicato a un parametro di un metodo.

Decorator di Classe

I decorator di classe sono decorator applicati alle classi. I decorator di classe sono scritti appena sopra la definizione della classe e possono accedere al costruttore della classe. Sono principalmente usati per modificare il comportamento della classe o aggiungere metadati.

 1function Logger(constructor: Function) {
 2    console.log(`Class ${constructor.name} is being constructed`);
 3}
 4
 5@Logger
 6class Person {
 7    constructor(public name: string) {}
 8}
 9
10const person = new Person('John');
11// Output: Class Person is being constructed

In questo esempio, il decorator Logger è applicato alla classe, e un messaggio viene mostrato nella console quando la classe è inizializzata.

Decorator di Metodo

I decorator di metodo sono applicati ai metodi di classe e possono alterare le chiamate o il comportamento del metodo. Un decoratore di metodo accetta tre argomenti.

  1. Il prototipo della classe
  2. Il nome del metodo
  3. Il descrittore della proprietà del metodo
 1function LogExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalMethod = descriptor.value;
 3
 4    descriptor.value = function (...args: any[]) {
 5        console.time(propertyKey);
 6        const result = originalMethod.apply(this, args);
 7        console.timeEnd(propertyKey);
 8        return result;
 9    };
10}
11
12class MathOperations {
13  @LogExecutionTime
14  add(a: number, b: number): number {
15    return a + b;
16  }
17}
18
19const math = new MathOperations();
20math.add(2, 3);
21// Output: add: 0.000ms (execution time is displayed)

In questo esempio, il decoratore LogExecutionTime viene applicato al metodo e il tempo di esecuzione del metodo viene registrato.

Decoratore Accessor

I decoratori Accessor vengono applicati al getter o setter delle proprietà della classe. Sono utili per aggiungere comportamenti quando si modificano i valori delle proprietà.

 1function LogAccess(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalGet = descriptor.get;
 3    const originalSet = descriptor.set;
 4
 5    if (originalGet) {
 6        descriptor.get = function () {
 7            console.log(`Getter called for ${propertyKey}`);
 8            return originalGet.call(this);
 9        };
10    }
11
12    if (originalSet) {
13        descriptor.set = function (value: any) {
14            console.log(`Setter called for ${propertyKey} with value: ${value}`);
15            originalSet.call(this, value);
16        };
17    }
18}
19
20class Car {
21    private _speed: number = 0;
22
23    @LogAccess
24    get speed() {
25        return this._speed;
26    }
27
28    set speed(value: number) {
29        this._speed = value;
30    }
31}
32
33const car = new Car();
34car.speed = 120;               // Setter called for speed with value: 120
35console.log(car.speed);       // Getter called for speed → 120

In questo esempio, un decoratore di accesso viene utilizzato per registrare l'output quando vengono chiamati il getter e il setter.

Decoratore di Proprietà

I decoratori di proprietà vengono applicati alle proprietà della classe ma non possono modificare direttamente il valore o il comportamento della proprietà. Vengono utilizzati per ottenere i metadati delle proprietà.

 1function Readonly(target: any, propertyKey: string) {
 2    Object.defineProperty(target, propertyKey, {
 3        writable: false
 4    });
 5}
 6
 7class Book {
 8    @Readonly
 9    title: string = "TypeScript Guide";
10}
11
12const book = new Book();
13book.title = "New Title"; // Error: Cannot assign to read only property 'title'

In questo esempio, il decoratore Readonly viene applicato alla proprietà title, rendendo la proprietà di sola lettura.

Decoratore di Parametri

I decoratori di parametri vengono applicati ai parametri di un metodo. Sono solitamente utilizzati per memorizzare metadati o convalidare i parametri. I decoratori accettano tre argomenti.

  1. Il prototipo della classe
  2. Il nome del metodo
  3. Indice del Parametro
 1function LogParameter(target: any, propertyKey: string, parameterIndex: number) {
 2    console.log(`Parameter at index ${parameterIndex} in method ${propertyKey} was decorated.`);
 3}
 4
 5class User {
 6    greet(@LogParameter message: string) {
 7        console.log(message);
 8    }
 9}
10
11const user = new User();
12user.greet('Hello!');
13// Output: Parameter at index 0 in method greet was decorated.

In questo esempio, il decoratore LogParameter è applicato al primo parametro del metodo greet, e quando il metodo viene chiamato, registra che il parametro è decorato.

Esempi Pratici di Decoratori

I decoratori sono ampiamente utilizzati in framework come Angular, soprattutto per l'iniezione delle dipendenze e la definizione dei metadati. Ad esempio, utilizza il decoratore @Component per definire i componenti di Angular come segue.

1@Component({
2    selector: 'app-root',
3    template: '<h1>Hello World</h1>',
4})
5export class AppComponent {}

Pertanto, i decoratori sono spesso utilizzati come parti fondamentali dei framework e delle librerie, aiutando a mantenere il codice conciso e chiaro.

Riepilogo dei Decoratori

I decoratori di TypeScript sono strumenti potenti che aggiungono funzionalità in modo flessibile a classi, metodi e proprietà. L'uso di decoratori personalizzati migliora la manutenibilità e la riutilizzabilità del codice, consentendo un'ulteriore astrazione. I decoratori svolgono un ruolo importante in framework come Angular e NestJS, e comprenderli aiuta a capire a fondo come funzionano questi framework.

Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.

YouTube Video