Decorators sind ein experimentelles und fortschrittliches Feature in
TypeScript, das aus dem Vorschlag für ECMAScript entstanden ist. Sie
ermöglichen Anmerkungen und eine metaprogrammierungsbasierte
syntaktische Art der Klassendeklarationen und erfordern das
Compiler-Flag "experimentalDecorators": true in der
tsconfig.json.
Decorators in TypeScript basieren auf einem ECMAScript-Vorschlag und befinden sich im Stadium 2 des ECMAScript-Vorschlagsprozesses. Da sie noch nicht endgültig im ECMAScript-Standard verankert sind, werden sie in TypeScript als experimentell behandelt, was bedeutet, dass sich ihre Implementierung in Zukunft ändern könnte.
Ein Klassen-Decorator wird direkt vor einer Klassendeklaration platziert. Er kann den Konstruktor erweitern und Metadaten hinzufügen:
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}Method-Decorators werden vor Methodendeklarationen angewendet:
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
let originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log("Calling " + propertyName);
return originalMethod.apply(this, args);
}
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@log
greet() {
return "Hello, " + this.greeting;
}
}Accessor-Decorators werden auf Getter und Setter angewendet:
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}
@configurable(false)
get x() { return this._x; }
@configurable(false)
get y() { return this._y; }
}Property-Decorators werden vor Eigenschaftsdeklarationen platziert:
function defaultToZero(target: any, propertyName: string) {
Object.defineProperty(target, propertyName, {
value: 0,
writable: true
});
}
class Example {
@defaultToZero
count: number;
}Parameter-Decorators werden direkt vor einem Parameterdeklarator verwendet:
function validate(target: any, propertyName: string, index: number) {
// Validierungslogik hier
}
class Greeter {
greet(@validate message: string) {
return "Hello, " + message;
}
}Vielen Dank für das bereitgestellte Beispiel. Ich werde es verwenden, um den Abschnitt über Funktionsdecorators in Ihrem Artikel zu überarbeiten. Hier ist die aktualisierte Version dieses Abschnitts:
Funktions-Decorators sind in TypeScript eine leistungsfähige
Möglichkeit, zusätzliche Funktionalität vor und nach der Ausführung
einer Methode einzufügen. Sie werden direkt vor der Methodendeklaration
platziert und können das Verhalten der Methode durch Modifikation des
PropertyDescriptor beeinflussen.
Das folgende Beispiel zeigt, wie ein Funktionsdecorator implementiert werden kann, um den Aufruf und die Ergebnisse einer Methode zu protokollieren:
function Log(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
// Logik vor der Ausführung der Methode
console.log(`Aufruf von ${propertyKey} mit Argumenten: ${JSON.stringify(args)}`);
// Ausführung der ursprünglichen Methode
const result = originalMethod.apply(this, args);
// Logik nach der Ausführung der Methode
console.log(`${propertyKey} wurde ausgeführt und gab zurück: ${result}`);
return result;
};
}
class MyClass {
@Log
myMethod(arg: string) {
console.log(`In myMethod: Argument = ${arg}`);
return `Result: ${arg}`;
}
}
const myObj = new MyClass();
myObj.myMethod("Testargument");In diesem Beispiel wird der @Log-Decorator verwendet, um
den Methodenaufruf von myMethod in der Klasse
MyClass zu protokollieren. Der Decorator fängt den Aufruf
der Methode ab, protokolliert die übergebenen Argumente, führt die
Methode aus, protokolliert das Ergebnis und gibt das Ergebnis zurück.
Dies ist besonders nützlich für Debugging-Zwecke, Performance-Messungen
oder zur Auditierung von Methodenaufrufen.