Валидация объектов в class-validator по умолчанию
выполняет проверку всех декораторов и всех правил для каждого свойства,
собирая полный список ошибок. Такой подход полезен для отображения всей
картины некорректных данных, но в ряде сценариев приводит к лишним
вычислениям и избыточному количеству сообщений об ошибках.
Параметр stopAtFirstError управляет стратегией остановки
процесса валидации и позволяет прекратить проверку сразу после
обнаружения первой ошибки.
stopAtFirstError определяет, будет ли процесс валидации
прерываться при первом же нарушении правила.
При значении:
false (по умолчанию) — проверяются все
свойства и все декораторы, собирается полный массив ошибокtrue — валидация прекращается сразу
после первой обнаруженной ошибкиКлючевой момент заключается в том, что остановка происходит не только на уровне объекта, но и внутри цепочки валидаторов одного свойства: дальнейшие проверки для текущего значения не выполняются.
Параметр передаётся в функцию validate или
validateOrReject через объект опций
ValidationOptions.
Пример базовой сигнатуры:
validate(object, {
stopAtFirstError: boolean
})
При стандартной настройке stopAtFirstError: false
выполняется полное прохождение по всем правилам:
import { validate } from "class-validator";
import { IsEmail, Length } from "class-validator";
class User {
@IsEmail()
email: string;
@Length(10, 20)
password: string;
}
const user = new User();
user.email = "invalid";
user.password = "123";
validate(user).then(errors => {
console.log(errors);
});
Результат содержит ошибки для обоих полей: email и
password, даже если первая ошибка уже очевидна.
При включении stopAtFirstError: true процесс завершается
при первом нарушении:
validate(user, {
stopAtFirstError: true,
}).then(errors => {
console.log(errors);
});
Если ошибка обнаружена в email, проверка
password может не выполняться вообще.
Поведение зависит от порядка объявленных свойств и последовательности применения декораторов.
class Account {
@Length(5, 10)
username: string;
@IsEmail()
email: string;
@Length(8, 20)
password: string;
}
При stopAtFirstError: true:
usernameТаким образом, порядок объявления напрямую влияет на результат валидации.
Каждое свойство может иметь несколько валидаторов:
class Product {
@IsString()
@Length(5, 50)
title: string;
}
При включённом stopAtFirstError:
IsString не проходит, Length не
выполняетсяЭто снижает количество вычислений, особенно при тяжёлых кастомных валидаторах.
Использование stopAtFirstError: true влияет на
производительность в больших структурах данных.
Основные эффекты:
Особенно заметно при:
Однако оптимизация имеет обратную сторону: отсутствие полного списка ошибок усложняет диагностику входных данных.
При использовании @ValidateNested() поведение становится
менее очевидным.
class Address {
@Length(10, 50)
street: string;
}
class User {
@ValidateNested()
address: Address;
}
При stopAtFirstError: true:
address.street, дальнейшие поля
User не проверяютсяЭто означает, что диагностика сложных структур становится «обрывочной».
При валидации массивов объектов:
class Item {
@IsString()
name: string;
}
class Order {
@ValidateNested({ each: true })
items: Item[];
}
stopAtFirstError: true влияет следующим образом:
Это критично в сценариях, где важно собрать полный список некорректных элементов.
skipMissingPropertiesПри комбинации с skipMissingProperties логика
меняется:
skipMissingProperties игнорирует
undefinedstopAtFirstError останавливает выполнение при первой
ошибкеВместе они приводят к максимально «лёгкой» валидации, где проверяется только минимально необходимый набор условий.
whitelist и forbidNonWhitelistedВ связке с ValidationOptions:
whitelist очищает лишние поляforbidNonWhitelisted выбрасывает ошибку при неизвестных
поляхПри включённом stopAtFirstError:
forbidNonWhitelisted может завершить
валидацию до проверки остальных свойствПоведение stopAtFirstError обычно оправдано в
случаях:
В системах с пользовательским интерфейсом чаще требуется обратный подход — полный список ошибок без прерывания процесса.