Функции в Joi представляют собой особый тип схем, предназначенный для проверки значений, которые должны быть функциями JavaScript. Такой тип валидации используется в ситуациях, когда необходимо гарантировать, что переданный параметр является вызываемым объектом и соответствует определённым характеристикам, связанным с его сигнатурой.
Схема для функции создаётся с помощью Joi.function().
Она проверяет, что значение действительно является функцией, то есть
имеет тип function в JavaScript.
const Joi = require('joi');
const schema = Joi.function();
schema.validate(() => {});
При передаче значения, не являющегося функцией, валидация завершится ошибкой:
schema.validate(123); // ошибка
schema.validate("text"); // ошибка
Основная задача Joi.function() — убедиться, что значение
относится к функциональному типу. Это включает как обычные функции, так
и стрелочные функции, а также асинхронные функции.
const schema = Joi.function();
schema.validate(function () {}); // валидно
schema.validate(() => {}); // валидно
schema.validate(async () => {}); // валидно
При этом важно учитывать, что валидация не анализирует внутреннюю логику функции, а работает исключительно на уровне типа.
Одной из ключевых возможностей является проверка количества
параметров функции. В Joi это называется arity.
const schema = Joi.function().arity(2);
Такое ограничение требует, чтобы функция имела строго два объявленных параметра:
schema.validate(function (a, b) {}); // валидно
schema.validate(function (a) {}); // ошибка
Важно учитывать, что проверяется именно объявленная сигнатура, а не фактическое количество переданных аргументов во время вызова.
Помимо строгого значения arity, доступны гибкие
ограничения:
Joi.function().minArity(1)
Joi.function().maxArity(3)
Означает, что функция должна принимать не менее указанного количества параметров:
const schema = Joi.function().minArity(2);
schema.validate(function (a, b) {}); // валидно
schema.validate(function (a, b, c) {}); // валидно
schema.validate(function (a) {}); // ошибка
Ограничивает максимальное число параметров:
const schema = Joi.function().maxArity(2);
schema.validate(function (a) {}); // валидно
schema.validate(function (a, b) {}); // валидно
schema.validate(function (a, b, c) {}); // ошибка
Методы могут комбинироваться для точной настройки сигнатуры:
const schema = Joi.function().minArity(1).maxArity(3);
Такое определение допускает функции с одним, двумя или тремя параметрами.
Для более сложных сценариев применяется метод custom,
позволяющий реализовать собственную логику проверки:
const schema = Joi.function().custom((value, helpers) => {
if (value.name === "") {
return helpers.error("function.invalidName");
}
return value;
});
Custom-валидация полезна, когда требуется анализ свойств функции, недоступных стандартным методам Joi.
Схемы функций поддерживают добавление метаданных, которые используются для документирования:
Joi.function().label("callback").description("Функция обратного вызова")
Эти свойства не влияют на саму валидацию, но помогают при генерации схем и отладке.
По умолчанию функция считается обязательным значением. Чтобы
разрешить отсутствие значения, используется optional:
const schema = Joi.function().optional();
schema.validate(undefined); // валидно
Функции в Joi не рассматриваются как объекты, даже несмотря на то,
что в JavaScript они технически являются объектами. Поэтому схема
Joi.object() не подходит для их проверки.
Joi.object().validate(() => {}); // ошибка
Joi.function().validate(() => {}); // валидно
Валидация функций применяется в конфигурациях библиотек и API, где функции передаются как параметры поведения:
const configSchema = Joi.object({
onSuccess: Joi.function().arity(1),
onError: Joi.function().minArity(2)
});
Асинхронные функции проходят проверку как обычные функции:
const schema = Joi.function();
schema.validate(async function () {}); // валидно
schema.validate(async () => {}); // валидно
Joi не анализирует Promise-логику или наличие await, так
как валидация работает исключительно на уровне структуры типа.
Функции, созданные через .bind, также распознаются как
валидные:
function test() {}
const bound = test.bind(null);
Joi.function().validate(bound); // валидно
При этом контекст выполнения и привязка this не влияют
на результат проверки.
Валидация функций в Joi имеет принципиальные ограничения:
Фактически проверка сводится к типу и сигнатуре объявления.
Функции-генераторы также проходят проверку как обычные функции:
function* generator() {}
Joi.function().validate(generator); // валидно
Joi не различает тип функции по способу её исполнения.
Часто используется комбинирование всех возможностей для строгого контроля API:
const handlerSchema = Joi.function()
.minArity(1)
.maxArity(2)
.label("eventHandler")
.required();
Такое определение задаёт чёткое поведение функции в рамках интерфейса, ограничивая её форму и обязательность передачи.