Skip to content

Instantly share code, notes, and snippets.

@kostark
Forked from remojansen/class_decorator.ts
Last active October 24, 2018 11:37
Show Gist options
  • Save kostark/9da58b051c03ce92a38e06c1cfbcaa85 to your computer and use it in GitHub Desktop.
Save kostark/9da58b051c03ce92a38e06c1cfbcaa85 to your computer and use it in GitHub Desktop.

Revisions

  1. kostark revised this gist Oct 24, 2018. No changes.
  2. @remojansen remojansen revised this gist Nov 17, 2015. 2 changed files with 39 additions and 0 deletions.
    14 changes: 14 additions & 0 deletions configurable_decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,14 @@
    @logClassWithArgs({ when : { name : "remo"} })
    class Person {
    public name: string;

    // ...
    }

    function logClassWithArgs(filter: Object) {
    return (target: Object) => {
    // implement class decorator here, the class decorator
    // will have access to the decorator arguments (filter)
    // because they are stored in a closure
    }
    }
    25 changes: 25 additions & 0 deletions reflect_metadata.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    function logParamTypes(target : any, key : string) {
    var types = Reflect.getMetadata("design:paramtypes", target, key);
    var s = types.map(a => a.name).join();
    console.log(`${key} param types: ${s}`);
    }

    class Foo {}
    interface IFoo {}

    class Demo{
    @logParameters
    doSomething(
    param1 : string,
    param2 : number,
    param3 : Foo,
    param4 : { test : string },
    param5 : IFoo,
    param6 : Function,
    param7 : (a : number) => void,
    ) : number {
    return 1
    }
    }

    // doSomething param types: String, Number, Foo, Object, Object, Function, Function
  3. @remojansen remojansen created this gist Nov 17, 2015.
    40 changes: 40 additions & 0 deletions class_decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    function logClass(target: any) {

    // save a reference to the original constructor
    var original = target;

    // a utility function to generate instances of a class
    function construct(constructor, args) {
    var c : any = function () {
    return constructor.apply(this, args);
    }
    c.prototype = constructor.prototype;
    return new c();
    }

    // the new constructor behaviour
    var f : any = function (...args) {
    console.log("New: " + original.name);
    return construct(original, args);
    }

    // copy prototype so intanceof operator still works
    f.prototype = original.prototype;

    // return new constructor (will override original)
    return f;
    }

    @logClass
    class Person {

    public name: string;
    public surname: string;

    constructor(name : string, surname : string) {
    this.name = name;
    this.surname = surname;
    }
    }

    var p = new Person("remo", "jansen");
    15 changes: 15 additions & 0 deletions decorator_factory.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    function log(...args : any[]) {
    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();
    }
    }
    45 changes: 45 additions & 0 deletions method_decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,45 @@
    function logMethod(target, key, descriptor) {

    // save a reference to the original method this way we keep the values currently in the
    // descriptor and don't overwrite what another decorator might have done to the descriptor.
    if(descriptor === undefined) {
    descriptor = Object.getOwnPropertyDescriptor(target, key);
    }
    var originalMethod = descriptor.value;

    //editing the descriptor/value parameter
    descriptor.value = function () {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
    args[_i - 0] = arguments[_i];
    }
    var a = args.map(function (a) { return JSON.stringify(a); }).join();
    // note usage of originalMethod here
    var result = originalMethod.apply(this, args);
    var r = JSON.stringify(result);
    console.log("Call: " + key + "(" + a + ") => " + r);
    return result;
    };

    // return edited descriptor as opposed to overwriting the descriptor
    return descriptor;
    }

    class Person {

    public name: string;
    public surname: string;

    constructor(name : string, surname : string) {
    this.name = name;
    this.surname = surname;
    }

    @logMethod
    public saySomething(something : string, somethingElse : string) : string {
    return this.name + " " + this.surname + " says: " + something + " " + somethingElse;
    }
    }

    var p = new Person("remo", "jansen");
    p.saySomething("I love playing", "halo");
    67 changes: 67 additions & 0 deletions parameter_decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    function logParameter(target: any, 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, key, descriptor) {

    if(descriptor === undefined) {
    descriptor = Object.getOwnPropertyDescriptor(target, key);
    }
    var originalMethod = descriptor.value;

    //editing the descriptor/value parameter
    descriptor.value = function (...args: any[]) {

    var metadataKey = `__log_${key}_parameters`;
    var indices = target[metadataKey];

    if (Array.isArray(indices)) {
    for (var i = 0; i < args.length; i++) {

    if (indices.indexOf(i) !== -1) {

    var arg = args[i];
    var argStr = JSON.stringify(arg) || arg.toString();
    console.log(`${key} arg[${i}]: ${argStr}`);
    }
    }
    var result = originalMethod.apply(this, args);
    return result;
    }
    else {
    var a = args.map(a => (JSON.stringify(a) || a.toString())).join();
    var result = originalMethod.apply(this, args);
    var r = JSON.stringify(result);
    console.log(`Call: ${key}(${a}) => ${r}`);
    return result;
    }
    }

    // return edited descriptor as opposed to overwriting the descriptor
    return descriptor;
    }

    class Person {

    public name: string;
    public surname: string;

    constructor(name : string, surname : string) {
    this.name = name;
    this.surname = surname;
    }

    @logMethod
    public saySomething(@logParameter something : string, somethingElse : string) : string {
    return this.name + " " + this.surname + " says: " + something + " " + somethingElse;
    }
    }

    var p = new Person("remo", "jansen");
    p.saySomething("I love playing", "halo");
    44 changes: 44 additions & 0 deletions property_decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    function logProperty(target: any, key: string) {

    // property value
    var _val = this[key];

    // property getter
    var getter = function () {
    console.log(`Get: ${key} => ${_val}`);
    return _val;
    };

    // property setter
    var setter = function (newVal) {
    console.log(`Set: ${key} => ${newVal}`);
    _val = newVal;
    };

    // Delete property.
    if (delete this[key]) {

    // Create new property with getter and setter
    Object.defineProperty(target, key, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    }
    }

    class Person {
    @logProperty
    public name: string;
    public surname: string;

    constructor(name : string, surname : string) {
    this.name = name;
    this.surname = surname;
    }
    }

    var p = new Person("remo", "Jansen");
    p.name = "Remo";
    var n = p.name;