В библиотеке Joi предусмотрен отдельный механизм принудительной
валидации через assert, предназначенный для ситуаций, когда
результат проверки должен гарантированно соответствовать схеме, иначе
выполнение логики считается некорректным.
assert отличается от стандартного validate
тем, что вместо возврата объекта с результатом и ошибками он выбрасывает
исключение при несоответствии данных. Это делает его особенно полезным в
слоях приложения, где отсутствие валидности данных является критической
ошибкой исполнения.
Базовая форма использования:
import Joi from 'joi';
Joi.assert(42, Joi.number().integer());
При несоответствии данных схеме генерируется исключение, содержащее подробности нарушения.
Дополнительный аргумент позволяет задать пользовательское сообщение:
Joi.assert('text', Joi.number(), 'Ожидалось числовое значение');
Сложные условия в контексте Joi возникают при необходимости проверки взаимозависимых полей, альтернативных структур данных и динамических правил, зависящих от состояния объекта.
Валидация перестаёт быть линейной, когда:
Joi предоставляет набор логических операторов для построения композитных правил.
Комбинации полей могут быть описаны через логические конструкции:
const schema = Joi.object({
a: Joi.number(),
b: Joi.number(),
c: Joi.number()
}).and('a', 'b');
В данном случае a и b обязаны
присутствовать одновременно.
Альтернативные условия:
Joi.object({
a: Joi.number(),
b: Joi.number()
}).or('a', 'b');
Смысл: хотя бы одно поле должно быть задано.
Исключающее поведение:
Joi.object({
a: Joi.number(),
b: Joi.number()
}).xor('a', 'b');
Допускается строго одно из полей.
Ключевой инструмент построения сложных условий — when,
позволяющий изменять схему в зависимости от значения другого поля.
const schema = Joi.object({
type: Joi.string().valid('email', 'phone').required(),
value: Joi.string().when('type', {
is: 'email',
then: Joi.string().email(),
otherwise: Joi.string().pattern(/^[0-9]+$/)
})
});
Здесь структура value динамически меняется в зависимости
от type.
Многоуровневые зависимости:
const schema = Joi.object({
role: Joi.string(),
access: Joi.number().when('role', {
switch: [
{ is: 'admin', then: Joi.number().min(10) },
{ is: 'user', then: Joi.number().max(5) }
],
otherwise: Joi.number().valid(0)
})
});
Сложные структуры часто требуют проверки отношений между полями, а не только их отдельных значений.
const schema = Joi.object({
min: Joi.number(),
max: Joi.number().greater(Joi.ref('min'))
});
Здесь max зависит от значения min, создавая
межполевую зависимость.
Дополнительные конструкции:
Joi.ref() — ссылка на другое полеgreater, less, min,
max с динамическими аргументамиКогда данные могут иметь несколько допустимых форм, применяется
alternatives.
const schema = Joi.alternatives().try(
Joi.string().email(),
Joi.string().pattern(/^[0-9]+$/),
Joi.object({
id: Joi.number()
})
);
Это позволяет описывать полиморфные структуры без необходимости ручной проверки типов.
Расширенный вариант:
Joi.alternatives().conditional('type', {
switch: [
{ is: 'A', then: Joi.object({ a: Joi.number() }) },
{ is: 'B', then: Joi.object({ b: Joi.string() }) }
]
});
Для сценариев, выходящих за рамки декларативных правил, применяется
custom.
const schema = Joi.number().custom((value, helpers) => {
if (value % 2 !== 0) {
return helpers.error('number.even');
}
return value;
});
Кастомные правила интегрируются в систему ошибок Joi и могут комбинироваться с другими ограничениями.
Сложные условия часто формируются через композицию:
const base = Joi.object({
id: Joi.number().required()
});
const extended = base.keys({
name: Joi.string().when('id', {
is: Joi.number().min(10),
then: Joi.required(),
otherwise: Joi.optional()
})
});
Композиция позволяет переиспользовать схемы без дублирования логики.
assert используется как финальная точка проверки, когда
вся система условий уже собрана в схему.
const schema = Joi.object({
role: Joi.string().required(),
permissions: Joi.array().items(Joi.string())
.when('role', {
is: 'admin',
then: Joi.required(),
otherwise: Joi.optional()
})
});
Joi.assert(
{ role: 'admin', permissions: [] },
schema
);
При нарушении любого из вложенных условий выполнение прерывается
исключением, что делает assert инструментом строгого
контроля целостности данных в сложных схемах.