Decorators in TypeScript

Decorators in TypeScript

Dieser Artikel erklärt Decorators in TypeScript.

YouTube Video

Decorators in TypeScript

TypeScript-Decorators sind ein Mechanismus, um zusätzlichen Funktionsumfang oder ein bestimmtes Verhalten zu Klassen, Methoden, Accessors, Eigenschaften oder Parametern hinzuzufügen. Decorators sind ein mächtiges Werkzeug zur Verbesserung der Lesbarkeit und Wiederverwendbarkeit von Code.

Grundlagen der Decorators

Ein Decorator ist eine Funktion, die einer Klasse oder ihren Mitgliedern zusätzliche Funktionalität hinzufügt. Decorators wurden in TypeScript 1.5 eingeführt und wurden außerdem für den ECMAScript-Standard vorgeschlagen.

1{
2  "compilerOptions": {
3    "experimentalDecorators": true
4  }
5}
  • Um Decorators zu verwenden, müssen Sie die Option experimentalDecorators in der Datei tsconfig.json aktivieren.

Arten von Decorators

In TypeScript können Sie die folgenden fünf Decorators verwenden:.

  • Klassen-Dekorator Ein Dekorator, der auf eine Klasse angewendet wird.
  • Methoden-Dekorator Ein Dekorator, der auf eine Methode einer Klasse angewendet wird.
  • Accessor-Dekorator Ein Dekorator, der auf einen Getter oder Setter einer Klassen-Eigenschaft angewendet wird.
  • Eigenschafts-Dekorator Ein Dekorator, der auf eine Eigenschaft einer Klasse angewendet wird.
  • Parameter-Dekorator Ein Dekorator, der auf einen Parameter einer Methode angewendet wird.

Klassen-Decorator

Klassen-Decorators sind Decorators, die auf Klassen angewendet werden. Klassen-Decorators werden direkt über der Klassendefinition geschrieben und können auf den Klassenkonstruktor zugreifen. Sie werden hauptsächlich verwendet, um das Verhalten von Klassen zu ändern oder Metadaten hinzuzufügen.

 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 diesem Beispiel wird der Logger-Decorator auf die Klasse angewendet, und eine Nachricht wird in der Konsole angezeigt, wenn die Klasse initialisiert wird.

Methoden-Decorator

Methoden-Decorators werden auf Klassenmethoden angewendet und können Methodenaufrufe und -verhalten verändern. Ein Methoden-Dekorator erhält drei Argumente.

  1. Der Prototyp der Klasse
  2. Der Name der Methode
  3. Der Eigenschaftsbeschreiber der Methode
 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 diesem Beispiel wird der LogExecutionTime-Dekorator auf die Methode angewendet, und die Ausführungszeit der Methode wird protokolliert.

Zugriffs-Dekorator

Zugriffs-Dekoratoren werden auf getter oder setter von Klasseigenschaften angewendet. Sie sind nützlich, um Verhalten beim Ändern von Eigenschaftswerten hinzuzufügen.

 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 diesem Beispiel wird ein Accessor-Decorator verwendet, um Ausgaben zu protokollieren, wenn der Getter und Setter aufgerufen werden.

Eigenschafts-Dekorator

Eigenschafts-Dekoratoren werden auf Klasseigenschaften angewendet, können jedoch den Wert oder das Verhalten der Eigenschaft nicht direkt ändern. Sie werden verwendet, um Metadaten von Eigenschaften zu erhalten.

 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 diesem Beispiel wird der Readonly-Dekorator auf die Eigenschaft title angewendet, und die Eigenschaft wird schreibgeschützt gemacht.

Parameter-Dekorator

Parameter-Dekoratoren werden auf die Parameter einer Methode angewendet. Sie werden in der Regel verwendet, um Metadaten zu speichern oder Parameter zu validieren. Dekoratoren nehmen drei Argumente entgegen.

  1. Der Prototyp der Klasse
  2. Der Name der Methode
  3. Parameterindex
 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 diesem Beispiel wird der LogParameter-Dekorator auf den ersten Parameter der Methode greet angewendet, und beim Aufruf der Methode wird protokolliert, dass der Parameter dekoriert ist.

Praktische Beispiele für Dekoratoren

Dekoratoren werden häufig in Frameworks wie Angular verwendet, insbesondere für Dependency Injection und Metadaten-Definition. Zum Beispiel wird der @Component-Dekorator verwendet, um Angular-Komponenten wie unten definiert zu erstellen.

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

Dekoratoren werden daher oft als Kernbestandteile von Frameworks und Bibliotheken verwendet, um den Code prägnant und klar zu halten.

Zusammenfassung der Dekoratoren

TypeScript-Dekoratoren sind leistungsstarke Werkzeuge, die flexibel Funktionalität zu Klassen, Methoden und Eigenschaften hinzufügen. Die Verwendung benutzerdefinierter Dekoratoren verbessert die Wartbarkeit und Wiederverwendbarkeit des Codes und ermöglicht eine weitere Abstraktion. Dekoratoren spielen eine wichtige Rolle in Frameworks wie Angular und NestJS, und das Verständnis ihrer Funktionsweise hilft dabei, diese Frameworks genauer zu verstehen.

Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.

YouTube Video