Строгая типизация в контексте Joi означает жёсткое соответствие входных данных заранее определённой схеме без автоматических преобразований, неявных приведений типов и допуска лишних полей. Основная цель такого подхода — предсказуемость валидации и исключение неоднозначного поведения при обработке пользовательских данных.
В стандартном режиме Joi может выполнять приведение типов (например,
строку "123" преобразовывать в число 123), а
также игнорировать или удалять неизвестные поля. При строгой типизации
эти механизмы отключаются или ограничиваются.
Строгая схема в Joi строится вокруг трёх ключевых аспектов:
1. Отключение преобразования типов 2. Запрет неявных полей и структурных изменений 3. Жёсткое определение обязательности значений
Каждый из этих аспектов может быть включён независимо, но в совокупности они формируют строгую модель проверки данных.
Joi по умолчанию пытается «исправить» входные данные. Например:
Joi.number().validate("42")
Результат — число 42, несмотря на то что вход был
строкой.
Для строгой типизации такое поведение недопустимо. Отключение
выполняется через convert: false:
const schema = Joi.number().prefs({ convert: false });
Теперь строка "42" не будет автоматически преобразована
в число и приведёт к ошибке валидации.
Аналогичный эффект можно задать глобально:
const schema = Joi.object({
age: Joi.number()
}).options({ convert: false });
Каждый тип в Joi имеет строгую интерпретацию:
Joi.string() — допускает только строкиJoi.number() — только числаJoi.boolean() — только булевы значенияJoi.object() — только объектыПри включённой строгой модели любые несоответствия типов приводят к ошибке без попыток преобразования.
Пример:
const schema = Joi.object({
id: Joi.number()
}).prefs({ convert: false });
schema.validate({ id: "10" });
Результат: ошибка, так как строка не преобразуется в число.
Строгая типизация требует явного указания обязательности полей.
Joi предоставляет три основных модификатора:
required() — поле обязательноoptional() — поле может отсутствоватьforbidden() — поле запрещеноПример строгой схемы:
const schema = Joi.object({
username: Joi.string().required(),
password: Joi.string().required(),
token: Joi.string().forbidden()
}).prefs({ convert: false });
В данном случае:
username или password приведёт
к ошибкеtoken приведёт к ошибкеОдним из ключевых элементов строгой типизации является контроль структуры объекта.
По умолчанию Joi может пропускать неизвестные поля или удалять их. Для строгого режима используется:
const schema = Joi.object({
name: Joi.string()
}).unknown(false);
или через опции:
const schema = Joi.object({
name: Joi.string()
}).options({ allowUnknown: false });
Теперь любой дополнительный ключ в объекте приведёт к ошибке.
Пример:
schema.validate({
name: "Alex",
age: 30
});
Результат — ошибка, так как age не описан в схеме.
Строгая типизация должна распространяться на все уровни вложенности.
const schema = Joi.object({
user: Joi.object({
id: Joi.number().required(),
email: Joi.string().required()
}).unknown(false)
}).prefs({ convert: false });
Здесь:
useridПри включённой строгой типизации результат валидации становится бинарным:
Пример результата ошибки:
{
"error": {
"message": "\"id\" must be a number",
"type": "number.base"
}
}
Иногда используется промежуточный режим между строгим и гибким подходом: удаление неизвестных полей.
const schema = Joi.object({
name: Joi.string()
}).stripUnknown(true);
В этом случае лишние поля не вызывают ошибку, но удаляются из результата.
Однако это уже не строгая типизация, а контролируемая фильтрация структуры.
На практике строгая схема формируется комбинацией параметров:
const schema = Joi.object({
id: Joi.number().required(),
name: Joi.string().required()
})
.unknown(false)
.options({ convert: false });
Такой подход фиксирует:
.strict()Joi предоставляет метод .strict(), который отключает
преобразования для конкретного типа:
const schema = Joi.number().strict();
Это эквивалентно:
Joi.number().prefs({ convert: false });
Однако .strict() применяется локально и удобен для
точечной настройки отдельных полей:
const schema = Joi.object({
id: Joi.number().strict(),
name: Joi.string()
});
Строгая модель снижает неоднозначность интерпретации данных и упрощает отладку, поскольку каждое несоответствие выявляется явно.
Дополнительный эффект:
При этом увеличивается чувствительность к ошибкам на уровне входных данных, что требует более точного контрактного описания схем.
Для массивов строгая типизация включает контроль элементов:
const schema = Joi.array().items(Joi.number().strict());
Здесь запрещены:
Любое несоответствие одного элемента приводит к ошибке всей структуры.
В строгом режиме часто используется фиксация структуры объекта:
const schema = Joi.object({
id: Joi.number(),
name: Joi.string()
}).length(2);
Это дополнительно гарантирует, что объект содержит ровно два поля.
При построении сложных схем важно поддерживать единый уровень строгости:
convertunknownrequiredНесогласованность приводит к частично строгим схемам, где поведение становится непредсказуемым.
Строгая типизация в Joi формируется набором ограничений: