How to implement a typescript decorator?是关于如何在打字稿中使用装饰器的一个很好的例子。
考虑以下情况,
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
可以是变量,函数和引用。
答案 0 :(得分:10)
你想要做的事情是不可能的。
在声明类时调用装饰器,此时没有实例传递给装饰器。
例如,使用以下代码:
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
设为静态,然后将其传递出去:@property({ afterDate: MyClass.startDateString })
。
答案 1 :(得分:3)
您无法从属性定义访问对象属性。
定义属性时会调用Decorator。
您可以在访问该属性时使用getter或setter来获取控制权。