Как передать переменную экземпляра в аргументы декоратора typescript?

Как реализовать декоратор typescript? - хороший пример того, как использовать декоратор в typescript.

Учитывая следующий случай,

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;
    };
}

Я пробовал все, но, похоже, у меня нет способа передать startDateString в аргумент декоратора. startDateString может быть переменной, функцией и ссылкой.

Ответ 1

То, что вы пытаетесь сделать, невозможно.

Декораторы вызываются при объявлении класса и в это время нет экземпляра, который должен пройти в декоратор.

Например, с помощью этого кода:

class MyClass {
    startDateString: string;
    @property({ afterDate: this.startDateString })
    endDateString: string;
}
let myClass = new MyClass();
  • MyClass объявлен.
  • Декораторы работают на MyClass. В этой точке нет экземпляра, который существует, и this в аргументе декоратора ссылается на глобальный объект, а не на экземпляр.
  • new MyClass() вызывается и создается экземпляр. На этом этапе декораторы не вызываются. Это уже произошло.

Взгляните на скомпилированный JavaScript для справки:

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();

Обратите внимание, что использование this.startDateString не генерирует ошибку компиляции, потому что this вводится как any.

Так что то, что делается здесь, путем передачи в свойстве экземпляра, не имеет смысла и не представляется возможным.

Что вы можете сделать, это сделать startDateString static, а затем передать его так: @property({ afterDate: MyClass.startDateString }).

Ответ 2

Вы не можете получить доступ к объекту из определения атрибута.

Decorator вызывается, когда свойство определено.

Вы можете использовать getter или setter для получения контроля при доступе к свойству.