Нельзя использовать валидировать внутри конструктора родительского класса с классом-валидатором - PullRequest
0 голосов
/ 24 декабря 2018

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

Я не знаю, как решить эту проблему, и, возможно, поместить проверку внутри конструкторов не очень хорошоидея.

Есть ли обходной путь или лучший способ сделать это?

1 Ответ

0 голосов
/ 24 декабря 2018

Причина, по которой вы получаете ошибку, не в том, что 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(), объявленный как в родительских, так и в дочерних классах.

...