Валидация элементов массива

В библиотеке Yup работа с массивами строится вокруг схемы array(), которая позволяет описывать не только структуру коллекции, но и правила для каждого её элемента. Ключевая особенность заключается в том, что валидатор применяется как к самому массиву целиком, так и к его внутренним значениям через метод of().

Базовая схема массива выглядит следующим образом:

import * as Yup from 'yup';

const schema = Yup.array();

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


Определение типа элементов массива через of()

Метод of() задаёт схему для каждого элемента массива. Это основной механизм типизации элементов.

const schema = Yup.array().of(
  Yup.string()
);

В данном случае каждый элемент массива обязан быть строкой. Любое значение другого типа приведёт к ошибке валидации.

Аналогично можно задавать числовые значения:

const schema = Yup.array().of(
  Yup.number()
);

Валидация сложных структур внутри массива

Элементы массива могут быть объектами с собственной схемой валидации. Yup позволяет комбинировать схемы любой сложности.

const schema = Yup.array().of(
  Yup.object({
    id: Yup.number().required(),
    name: Yup.string().min(2).required(),
    isActive: Yup.boolean()
  })
);

Каждый объект внутри массива проходит независимую проверку по заданной структуре.


Ограничение длины массива

Для управления размером коллекции используются методы min() и max().

const schema = Yup.array()
  .min(1, 'Массив не должен быть пустым')
  .max(5, 'Слишком много элементов');

Также можно использовать length() для строгого контроля:

const schema = Yup.array()
  .length(3, 'Должно быть ровно 3 элемента');

Обязательность массива и пустые значения

Метод required() определяет, что значение не должно быть undefined или null.

const schema = Yup.array().required();

Однако важно учитывать различие между отсутствием массива и пустым массивом. Пустой массив остаётся валидным значением, если не задано ограничение min().


Проверка уникальности элементов

Для обеспечения уникальности значений используется кастомная проверка через test().

const schema = Yup.array().test(
  'unique',
  'Элементы должны быть уникальными',
  (value) => {
    if (!value) return true;
    return new Set(value).size === value.length;
  }
);

Для массивов объектов проверка усложняется:

const schema = Yup.array().test(
  'unique-id',
  'ID должны быть уникальными',
  (value) => {
    if (!value) return true;
    const ids = value.map(item => item.id);
    return new Set(ids).size === ids.length;
  }
);

Предобработка массива через transform()

Метод transform() позволяет изменять входные данные до валидации. Это часто используется для нормализации значений.

const schema = Yup.array().transform((value, originalValue) => {
  if (typeof originalValue === 'string') {
    return originalValue.split(',');
  }
  return value;
});

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


Очистка некорректных элементов через compact()

Метод compact() удаляет элементы, которые считаются “пустыми” или невалидными.

const schema = Yup.array().compact((value) => {
  return value === null || value === undefined;
});

Это позволяет автоматически очищать массив перед основной валидацией.


Валидация вложенных массивов

Yup поддерживает многомерные структуры, включая массивы массивов.

const schema = Yup.array().of(
  Yup.array().of(
    Yup.number().required()
  )
);

Такая схема полезна для матриц, таблиц и сложных структур данных.


Условная валидация элементов массива

С помощью when() можно изменять правила в зависимости от контекста.

const schema = Yup.array().of(
  Yup.object({
    type: Yup.string(),
    value: Yup.mixed().when('type', {
      is: 'number',
      then: Yup.number(),
      otherwise: Yup.string()
    })
  })
);

Условная логика позволяет адаптировать схему под динамические данные.


Кастомная валидация элементов через test()

Каждый элемент массива может проверяться по сложным правилам.

const schema = Yup.array().of(
  Yup.string().test(
    'no-spaces',
    'Строка не должна содержать пробелы',
    (value) => {
      if (!value) return true;
      return !value.includes(' ');
    }
  )
);

Использование lazy для динамических элементов

Метод lazy() позволяет определять схему элемента в момент валидации.

const schema = Yup.array().of(
  Yup.lazy((value) => {
    if (typeof value === 'number') {
      return Yup.number().min(0);
    }
    return Yup.string();
  })
);

Это особенно полезно при работе с неоднородными массивами.


Комбинирование схем для сложных коллекций

В реальных сценариях массивы часто содержат комбинации правил:

const schema = Yup.array()
  .min(1)
  .max(10)
  .of(
    Yup.object({
      id: Yup.number().required(),
      tags: Yup.array().of(Yup.string().min(1)).min(1)
    })
  )
  .compact()
  .required();

Такая композиция позволяет одновременно контролировать структуру, содержимое и целостность данных.


Обработка ошибок на уровне элементов

Yup формирует детализированные сообщения об ошибках для каждого элемента массива. Индексация помогает точно определить проблемное значение:

errors[2].name must be a string

Это особенно важно при валидации форм с динамическими списками, где требуется точечная диагностика.


Производительность при больших массивах

При работе с большими коллекциями критически важно учитывать количество проверок. Использование lazy(), минимизация test() и упрощение схемы of() позволяет снизить нагрузку на валидацию.

Дополнительный эффект даёт предварительная нормализация данных через transform(), уменьшая количество операций внутри основной схемы.


Типичные ошибки при валидации массивов

Часто встречаются ситуации, связанные с неправильной интерпретацией типов:

  • передача строки вместо массива
  • отсутствие of() при ожидании структурированных элементов
  • использование required() без учёта пустого массива
  • некорректная проверка уникальности объектов

Корректное построение схемы требует строгого разделения валидации массива и валидации его элементов, поскольку Yup обрабатывает эти уровни независимо.