Невозможно использовать проверку внутри конструктора родительского класса с классом-валидатором

Я хочу использовать 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 не имеет атрибута породы, код выдает ошибку, указанную выше.

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

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
2 829
1

Ответы 1

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

TheGorgeousSeal 24.12.2018 14:28

Другие вопросы по теме