Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass an instance variable into typescript decorator arguments?

How to implement a typescript decorator? is a good example about how to use decorator in typescript.

Considering the below case,

class MyClass {
    @enumerable(false)
    get prop() {
        return true;
    }

    @property({required: true}) //here pass constant is no issue
    public startDateString:string;

    @property({afterDate: this.startDateString}) //how to pass startDateString here?
    public endDateString:string;
}

function enumerable(isEnumerable: boolean) {
    return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
        descriptor.enumerable = isEnumerable;
        return descriptor;
    };
}

I tried everything but it seems I have no way to pass startDateString into decorator argument. startDateString could be a variable, a function and a reference.

like image 248
new2cpp Avatar asked Jan 13 '16 00:01

new2cpp


2 Answers

What you are trying to do is not possible.

Decorators get called when the class is declared and at this time there is no instance to pass into the decorator.

For example, with this code:

class MyClass {
    startDateString: string;
    @property({ afterDate: this.startDateString })
    endDateString: string;
}
let myClass = new MyClass();
  1. MyClass is declared.
  2. The decorators are run on MyClass. There is no instance that exists to pass in at this point and this in the decorator argument refers to the global object—not an instance.
  3. new MyClass() is called and the instance is created. Decorators aren't called on this step. That already happened.

Take a look at the compiled JavaScript for reference:

var MyClass = (function () {
    // -- 1 --
    function MyClass() {
    }
    // -- 2 --
    __decorate([
        // see here... `this` is equal to the global object
        property({ afterDate: this.startDateString })
    ], MyClass.prototype, "endDateString", void 0);
    return MyClass;
})();
// -- 3 --
var myClass = new MyClass();

Note that using this.startDateString doesn't throw a compile error here because this is typed as any.

So what is trying to be done here by passing in an instance property doesn't make sense and isn't possible.

What you could do is make startDateString static then pass it in like so: @property({ afterDate: MyClass.startDateString }).

like image 193
David Sherret Avatar answered Sep 20 '22 09:09

David Sherret


You can't access to a object property from a attribute definition.

Decorator is called when the property is defined.

You could use getter or setter to get control when access to the property.

like image 35
Javier Ros Avatar answered Sep 19 '22 09:09

Javier Ros