Функции: function()

Функции в Joi представляют собой особый тип схем, предназначенный для проверки значений, которые должны быть функциями JavaScript. Такой тип валидации используется в ситуациях, когда необходимо гарантировать, что переданный параметр является вызываемым объектом и соответствует определённым характеристикам, связанным с его сигнатурой.

Схема для функции создаётся с помощью Joi.function(). Она проверяет, что значение действительно является функцией, то есть имеет тип function в JavaScript.

const Joi = require('joi');

const schema = Joi.function();

schema.validate(() => {});

При передаче значения, не являющегося функцией, валидация завершится ошибкой:

schema.validate(123); // ошибка
schema.validate("text"); // ошибка

Проверка типа Function

Основная задача Joi.function() — убедиться, что значение относится к функциональному типу. Это включает как обычные функции, так и стрелочные функции, а также асинхронные функции.

const schema = Joi.function();

schema.validate(function () {}); // валидно
schema.validate(() => {}); // валидно
schema.validate(async () => {}); // валидно

При этом важно учитывать, что валидация не анализирует внутреннюю логику функции, а работает исключительно на уровне типа.

Ограничение количества аргументов (arity)

Одной из ключевых возможностей является проверка количества параметров функции. В 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)

minArity

Означает, что функция должна принимать не менее указанного количества параметров:

const schema = Joi.function().minArity(2);

schema.validate(function (a, b) {}); // валидно
schema.validate(function (a, b, c) {}); // валидно
schema.validate(function (a) {}); // ошибка

maxArity

Ограничивает максимальное число параметров:

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-валидацию

Для более сложных сценариев применяется метод 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("Функция обратного вызова")

Эти свойства не влияют на саму валидацию, но помогают при генерации схем и отладке.

Поведение с undefined и optional значениями

По умолчанию функция считается обязательным значением. Чтобы разрешить отсутствие значения, используется optional:

const schema = Joi.function().optional();

schema.validate(undefined); // валидно

Отличие от объектной валидации

Функции в Joi не рассматриваются как объекты, даже несмотря на то, что в JavaScript они технически являются объектами. Поэтому схема Joi.object() не подходит для их проверки.

Joi.object().validate(() => {}); // ошибка
Joi.function().validate(() => {}); // валидно

Типичные сценарии использования

Валидация функций применяется в конфигурациях библиотек и API, где функции передаются как параметры поведения:

  • обработчики событий
  • middleware-функции
  • callback-функции
  • стратегии обработки данных
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 и контекстом

Функции, созданные через .bind, также распознаются как валидные:

function test() {}
const bound = test.bind(null);

Joi.function().validate(bound); // валидно

При этом контекст выполнения и привязка this не влияют на результат проверки.

Ограничения и особенности

Валидация функций в Joi имеет принципиальные ограничения:

  • не проверяется тело функции
  • не анализируется возвращаемое значение
  • не оценивается выполнение async/await
  • не учитываются динамические параметры arguments

Фактически проверка сводится к типу и сигнатуре объявления.

Поведение с генераторами

Функции-генераторы также проходят проверку как обычные функции:

function* generator() {}

Joi.function().validate(generator); // валидно

Joi не различает тип функции по способу её исполнения.

Итоговые комбинации правил

Часто используется комбинирование всех возможностей для строгого контроля API:

const handlerSchema = Joi.function()
  .minArity(1)
  .maxArity(2)
  .label("eventHandler")
  .required();

Такое определение задаёт чёткое поведение функции в рамках интерфейса, ограничивая её форму и обязательность передачи.