Javascript 如何使类装饰器仅在继承链中最外层的类上运行?
我使用decorator在运行时验证涉及来自应用程序外部的数据的数据类。我希望我的类在实例化时进行自我验证。我已经编写了一个类装饰器来轻松地将此功能添加到类中Javascript 如何使类装饰器仅在继承链中最外层的类上运行?,javascript,typescript,inheritance,decorator,Javascript,Typescript,Inheritance,Decorator,我使用decorator在运行时验证涉及来自应用程序外部的数据的数据类。我希望我的类在实例化时进行自我验证。我已经编写了一个类装饰器来轻松地将此功能添加到类中 import * as t from 'class-validator'; interface Class { new(...args: any[]): {}; } export function autoValidate<T extends Class>(target: T) { return class ext
import * as t from 'class-validator';
interface Class {
new(...args: any[]): {};
}
export function autoValidate<T extends Class>(target: T) {
return class extends target {
constructor(...args: any[]) {
super(...args);
const errors = t.validateSync(this);
if (errors.length > 0) {
throw errors;
}
}
};
}
当实例化Child
时,当在Child
的构造函数/装饰器中调用super
时,验证器将在父构造函数的装饰器中抛出一个错误,因为happy
是未定义的
如果这是目标的一个实例,而不是目标的后代,我如何修改我的decorator,使其只运行其验证代码?基于Patrick Roberts想法的解决方案,具有额外的保护,防止定义子类和忘记@autoValidate
(否则将导致根本没有验证):
import*作为t从“类验证器”导入;
接口类{
新(…args:any[]):{};
}
const lastClassWithValidation=Symbol();
导出函数自动验证(目标:T){
返回类扩展了目标{
静态[lastClassWithValidation]=目标;
构造函数(…参数:任意[]){
超级(…args);
if((this.constructor)[lastClassWithValidation]==目标){
const errors=t.validateSync(this);
如果(errors.length>0){
抛出错误;
}
}
}
};
}
if(this.constructor==target)
?@PatrickRoberts我想你很接近了,但是这个。构造函数将是包装类,永远不会等于目标
,所以装饰者需要保存包装类,这样这个。构造函数
可以与之相比。想用这个更正的答案写一个吗?在我看来,这样做不会太麻烦<代码>if(Object.getPrototypeOf(this.constructor)==target)
,这样就不会污染类的静态属性和实现细节。@PatrickRoberts,这种方式不提供针对没有@autoValidate
的子类的保护。如果不需要这种保护,当然可以。如果需要,自然会使用符号。我不相信使用字符串是正确的ed静态属性是个大问题,但是使用符号很容易,所以我更新了答案。使用符号可以避免在将类序列化为JSON时拾取成员。
@autoValidate
class Parent {
@t.IsNumber()
readonly age: number;
@t.IsString()
readonly name: string;
constructor(age: number, name: string) {
this.age = age;
this.name = name;
}
}
@autoValidate
class Child extends Parent {
@t.IsBoolean()
readonly happy: boolean;
constructor(age: number, name: string, happy: boolean) {
super(age, name);
this.happy = happy;
}
}
import * as t from 'class-validator';
interface Class {
new(...args: any[]): {};
}
const lastClassWithValidation = Symbol();
export function autoValidate<T extends Class>(target: T) {
return class extends target {
static [lastClassWithValidation] = target;
constructor(...args: any[]) {
super(...args);
if ((<any>this.constructor)[lastClassWithValidation] === target) {
const errors = t.validateSync(this);
if (errors.length > 0) {
throw errors;
}
}
}
};
}