Я хочу использовать 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.info("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.info("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 (), а затем this.validate () класса Animal. Этот метод проверяет экземпляр Dog, и, поскольку Animal не имеет атрибута породы, код выдает ошибку, указанную выше.
Я не знаю, как решить эту проблему, и, возможно, вставлять валидацию внутри конструкторов - не лучшая идея.
Есть ли обходной путь или лучший способ сделать это?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Причина, по которой вы получаете ошибку, заключается не в том, что у 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(), объявленный как в родительском, так и в дочернем классах.
Да, я так и думал. Единственное, чего я хочу, - это избегать проверки свойств вне конструктора. Кроме того, поскольку можно создать экземпляр класса Animal (потому что это не абстрактный класс), я не могу вызвать validate () внутри конструктора (по причинам, которые вы указали), поэтому не рекомендуется вызывать проверку только для дочерние классы. Как вы сказали, единственное разумное решение - вызвать проверку после создания экземпляра. Спасибо :)