Dekoratory w języku TypeScript zapewniają możliwość programowej ingerencji w proces definiowania klas. Trzeba pamiętać, że definicja klasy opisuje jej postać. Innymi słowy, definicja klasy określa, jakie dana klasa będzie mieć właściwości oraz metody. Z kolei te właściwości i metody stają się dostępne wyłącznie po utworzeniu instancji danej klasy.
// Dekoratory
// ==========
// składnia dekoratorów
// ================
function simpleDecorator(constructor : Function) {
console.log('Wywołano funkcję simpleDecorator.');
}
@simpleDecorator
class ClassWithSimpleDecorator {
}
let instance_1 = new ClassWithSimpleDecorator();
let instance_2 = new ClassWithSimpleDecorator();
console.log(`instance_1 : ${instance_1}`);
console.log(`instance_2 : ${instance_2}`);
function secondDecorator(constructor : Function) {
console.log('Wywołano funkcję secondDecorator.')
}
@simpleDecorator
@secondDecorator
class ClassWithMultipleDecorators {
}
// fabryki dekoratorów
// ===================
function decoratorFactory(name: string) {
return function (constructor : Function ) {
console.log(`funkcja dekortora wywołana z parametrem : ${name}`);
}
}
@decoratorFactory('nazwaTestowa')
class ClassWithDecoratorFactory {
}
// parametry dekoratorów klas
// ==========================
function classConstructorDec(constructor: Function) {
console.log(`constructor : ${constructor}`);
console.log(`constructor.name : ${(<any>constructor).name}`);
constructor.prototype.testProperty = "wartość_testProperty";
}
@classConstructorDec
class ClassWithConstructor {
}
let classConstrInstance = new ClassWithConstructor();
console.log(`classConstrInstance.testProperty : `
+ `${(<any>classConstrInstance).testProperty}`);
// dekoratory właściwości
// ===================
function propertyDec(target: any, propertyKey : string) {
console.log(`target: ${target}`);
console.log(`target.constructor: ${target.constructor}`);
console.log(`target.constructor.name: `
+ `${target.constructor.name}`);
console.log(`propertyKey: ${propertyKey}`);
}
class ClassWithPropertyDec {
@propertyDec
name: string;
}
//function propertyDec(target: any, propertyKey : string) {
// // console.log(`target : ${target}`);
// // console.log(`target.constructor : ${target.constructor}`);
//
// if(typeof(target) === 'function') {
// console.log(`nazwa klasy: ${target.name}`);
// } else {
// console.log(`nazwa klasy: ${target.constructor.name}`);
// }
//
// console.log(`propertyKey : ${propertyKey}`);
//}
//class ClassWithPropertyDec {
// @propertyDec
// propname: string;
//}
class StaticClassWithPropertyDec {
@propertyDec
static propname: string;
}
// dekoratory metod
// =================
function methodDec (target: any,
methodName: string,
descriptor?: PropertyDescriptor) {
console.log(`target: ${target}`);
console.log(`methodName: ${methodName}`);
console.log(`target[methodName]: ${target[methodName]}`);
}
class ClassWithMethodDec {
@methodDec
print(output: string) {
console.log(`Wywołano metodę `
+ `ClassWithMethodDec.print(${output}).`);
}
}
// stosowanie dekoratorów metod
// =======================
function auditLogDec(target: any,
methodName: string,
descriptor?: PropertyDescriptor ) {
let originalFunction = target[methodName];
let auditFunction = function() {
console.log(`auditLogDec: wywołano podmienioną `
+ `wersję metody ${methodName}. `);
originalFunction.apply(this, arguments);
}
target[methodName] = auditFunction;
return target;
}
class ClassWithAuditDec {
@auditLogDec
print(output: string) {
console.log(`Wywołano metodę `
+ `ClassWithMethodDec.print(${output}).`);
}
}
let auditClass = new ClassWithAuditDec();
auditClass.print("testy");
// dekoratory parametrów
// ====================
function parameterDec(target: any,
methodName : string,
parameterIndex: number) {
console.log(`target: ${target}`);
console.log(`methodName : ${methodName}`);
console.log(`parameterIndex : ${parameterIndex}`);
}
class ClassWithParamDec {
print(@parameterDec value: string) {
}
}
// metadane dekoratorów
// ==================
// należy wykonać następujące polecenia:
// npm install reflect-metadata --save
// npm install @types/reflect-metadata --save
import 'reflect-metadata';
function metadataParameterDec(target: any,
methodName : string,
parameterIndex: number) {
let designType = Reflect.getMetadata(
"design:type", target, methodName);
console.log(`designType: ${designType}`)
let designParamTypes = Reflect.getMetadata(
"design:paramtypes", target, methodName);
console.log(`paramtypes : ${designParamTypes}`);
let designReturnType = Reflect.getMetadata(
"design:returntype", target, methodName);
console.log(`returntypes : ${designReturnType}`);
}
class ClassWithMetaData {
print(
@metadataParameterDec
id: number,
name: string) : number {
return 1000;
}
}
//*/