我想在对象构造函数中使用validateSync,但无法将其用于继承。
我有这样的东西:
import { IsNotEmpty, IsString, validateSync, validate } from 'class-validator';
class Animal {
@IsNotEmpty()
@IsString()
public name: string;
constructor(name: string) {
this.name = name;
this.validate() // this method calls validate of class Dog, since this is an instance of Dog
}
protected validate() {
const errors = validateSync(this);
if (errors.length > 0) {
console.log("Animal validation error: ", errors)
}
}
}
class Dog extends Animal {
@IsNotEmpty()
@IsString()
public breed: string;
constructor(name: string, breed: string) {
super(name);
this.breed = breed
this.validate()
}
protected validate() {
const errors = validateSync(this);
if (errors.length > 0) {
console.log("Dog validation error: ", errors)
}
}
}
const dog = new Dog('Aaron', 'Golden Retriever')
结果是:
Dog validation error: [ ValidationError {
target: Dog { name: 'Aaron' },
value: undefined,
property: 'breed',
children: [],
constraints:
{ isString: 'breed must be a string',
isNotEmpty: 'breed should not be empty' } } ]
当我调用Dog构造函数时,代码先运行super(),然后运行Animal类的this.validate()。此方法将验证Dog的实例,并且由于Animal没有品种属性,因此代码将引发上面的错误。
我不知道如何解决这个问题,也许将验证放入构造函数中不是一个好主意。
是否有解决方法或更好的方法?
答案 0 :(得分:2)
出现错误的原因不是因为Animal
没有breed
属性(实际上是因为实例实际上是Dog
),而是因为您调用了在设置要验证的所有值之前,先进行验证(其中之一)。另一件事是,您进行了两次验证,听起来不正确。
class Dog extends Animal {
constructor(name: string, breed: string) {
super(name); // <-- validation gets called in the parent but you did't set the breed property yet
this.breed = breed;
this.validate(); // <-- validation gets called for the second time, but this time it passes
}
}
由于super()
必须是构造函数中的第一条语句,因此您无法用当前的模式来避免这种情况。
一种解决方案是避免在基类中调用validate()
,让子类正确设置所有字段,然后再进行验证。
在验证构造函数中的必需属性时,我没有看到任何错误,因为您正在阻止创建具有无效状态的对象。但是,如果在创建对象时并非绝对必须具有所有值,则建议让调用者决定何时进行验证:
const dog = new Dog('Aaron');
// do some stuff like determine the breed...
dog.breed = 'Golden Retriever';
// do some more stuff
const validationResult = dog.validate(); // did I succeed?
另外请注意,您似乎不需要在父类和子类中都声明相同的确切方法validate()
。