Created
January 22, 2016 14:03
-
-
Save frontdevops/0196eb8e8f315d0b7d72 to your computer and use it in GitHub Desktop.
TypeScript decorators example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//"use strict"; | |
function logProperty(target:Object, key:string):void { | |
var val:any = this[key]; | |
const getter = function():any { | |
console.log(`Get: ${key} => ${val}`); | |
return val; | |
}; | |
const setter = function (newVal):void { | |
console.log(`Set: ${key} => ${newVal}`); | |
val = newVal; | |
}; | |
if (delete this[key]) | |
Object.defineProperty(target, key, { | |
get: getter, | |
set: setter, | |
enumerable: true, | |
configurable: true | |
}); | |
} | |
function logParameter(target:Object, key:string, index:number) { | |
var metadataKey = `log_${key}_parameters`; | |
if (Array.isArray(target[metadataKey])) { | |
target[metadataKey].push(index); | |
} | |
else { | |
target[metadataKey] = [index]; | |
} | |
} | |
function logMethod(target:any, key:string, descriptor:any) { | |
var originalMethod = descriptor.value; | |
descriptor.value = function (...args:any[]) { | |
var indices = target[`__log_${key}_parameters`]; | |
if (Array.isArray(indices)) { | |
for (let i = 0; i < args.length; i++) { | |
if (indices.indexOf(i) !== -1) { | |
let arg = args[i]; | |
let argStr = JSON.stringify(arg) || arg.toString(); | |
console.log(`${key} arg[${i}]: ${argStr}`); | |
} | |
} | |
return originalMethod.apply(this, args); | |
} | |
let a = args.map(a => (JSON.stringify(a) || a.toString())).join(); | |
let result = originalMethod.apply(this, args); | |
let cln = target.constructor.name; | |
console.log(`Call: ${cln}.${key}(${a}) => ${JSON.stringify(result)}`); | |
return result; | |
}; | |
return descriptor; | |
} | |
function logClass(target:Object):Object { | |
var original = target; | |
function construct(constructor, args) { | |
let c:any = function(){ | |
return constructor.apply(this, args); | |
}; | |
c.prototype = constructor.prototype; | |
return new c; | |
} | |
let f:any = (...args) => { | |
console.log(`New: ${original.name}`); | |
return construct(original, args); | |
}; | |
f.prototype = original.prototype; | |
return f; | |
} | |
function log(...args : any[]):any { | |
args = args.filter(n=>n!=undefined); | |
switch(args.length) { | |
case 1: return logClass.apply(this, args); | |
case 2: return logProperty.apply(this, args); | |
case 3: | |
if(typeof args[2] === "number") | |
return logParameter.apply(this, args); | |
return logMethod.apply(this, args); | |
default: throw new Error("Decorators are not valid here!"); | |
} | |
} | |
@log | |
class Person { | |
@log public name:string; | |
@log public surname:string; | |
constructor(name:string, surname:string) { | |
this.name = name; | |
this.surname = surname; | |
} | |
@log | |
public say(@log message:string):string { | |
return `${this.name} ${this.surname} says: ${message}`; | |
} | |
} | |
let me = new Person("Alex", "Mayorov"); | |
let you = new Person("Kira", "Hagakyre"); | |
me.say('Hi, Kira!'); | |
you.say('Hi, Alex!'); | |
/* Output: | |
New: Person | |
Set: name => Alex | |
Set: surname => Mayorov | |
New: Person | |
Set: name => Kira | |
Set: surname => Hagakyre | |
Get: name => Kira | |
Get: surname => Hagakyre | |
Call: Person.say("Hi, Kira!") => "Kira Hagakyre says: Hi, Kira!" | |
Get: name => Kira | |
Get: surname => Hagakyre | |
Call: Person.say("Hi, Alex!") => "Kira Hagakyre says: Hi, Alex!" | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment