Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使类装饰器仅在继承链中最外层的类上运行?_Javascript_Typescript_Inheritance_Decorator - Fatal编程技术网

Javascript 如何使类装饰器仅在继承链中最外层的类上运行?

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

我使用decorator在运行时验证涉及来自应用程序外部的数据的数据类。我希望我的类在实例化时进行自我验证。我已经编写了一个类装饰器来轻松地将此功能添加到类中

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