Skip to content

Instantly share code, notes, and snippets.

@thatseeyou
Created November 13, 2016 15:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thatseeyou/4573714b21fe9f181381886f21b8e6b0 to your computer and use it in GitHub Desktop.
Save thatseeyou/4573714b21fe9f181381886f21b8e6b0 to your computer and use it in GitHub Desktop.
TypeScript 2.0 Decorators example
// npm i reflect-metadata --save
//import "reflect-metadata";
import "core-js" // Using Symbol for ES5 target
@sealed
class Greeter {
@propertyDecorator
private _greeting: string;
constructor(message: string) {
this._greeting = message;
}
@methodTrace(true)
greet(msg: string) {
return `Hello, ${this._greeting} : ${msg}`;
}
@methodTrace(false)
@validate
greet2(msg: string, @required msg2: string) {
return `Hi, ${this._greeting} : ${msg} - ${msg2}`;
}
@methodTrace(true)
get greeting() {
return this._greeting;
}
set greeting(newValue) {
this._greeting = newValue;
}
}
let a: Greeter = new Greeter('World');
a.greeting = 'Universe';
console.log(a.greeting);
console.log(a.greet('It\'s me'));
console.log(a.greet2('It\'s me', undefined));
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
function methodTrace(debug: boolean) {
console.log('Call methodTraceDecoratorFactory');
if (debug) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log('Call methodTraceDecorator');
console.log(` target = ${target}, propertyKey = ${propertyKey}, descriptor = ${descriptor}`);
for (let key of ['get', 'set', 'value']) {
if (descriptor[key]) {
let origFunc = descriptor[key];
descriptor[key] = makeLogMethod(origFunc);
}
}
return descriptor;
function makeLogMethod(origFunc: Function) {
return function logMethod(this: Object, ...args: any[]) {
let result = origFunc.apply(this, args);
let a = args.map(a => JSON.stringify(a)).join();
let r = JSON.stringify(result);
console.log(`Call: ${propertyKey}(${a}) => ${r}`);
return result;
}
}
}
}
else {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
console.log('Call methodTraceDecorator -> No Return');
console.log(` target = ${target}, propertyKey = ${propertyKey}, descriptor = ${descriptor}`);
}
}
}
function propertyDecorator(target: any, propertyKey: string) {
console.log('Call propertyDecorator');
console.log(` target = ${target}, propertyKey = ${propertyKey}`);
//console.log(target);
}
const requiredMetadataKey = Symbol("required");
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
console.log('Call required');
console.log(` target = ${target}, propertyKey = ${propertyKey}, parameterIndex = ${parameterIndex}`);
let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [];
existingRequiredParameters.push(parameterIndex);
Reflect.defineMetadata(requiredMetadataKey, existingRequiredParameters, target, propertyKey);
}
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
console.log('Call validate');
console.log(` target = ${target}, propertyName = ${propertyName}, descriptor = ${descriptor}`);
let method = descriptor.value;
descriptor.value = function (this:Object) {
let requiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyName);
if (requiredParameters) {
for (let parameterIndex of requiredParameters) {
if (parameterIndex >= arguments.length || arguments[parameterIndex] === undefined) {
throw new Error("Missing required argument.");
}
}
}
return method.apply(this, arguments);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment