Валидация массивов в Yup строится вокруг декларативного описания
структуры данных и последовательного применения трансформаций и
ограничений. Одним из ключевых механизмов предварительной очистки данных
внутри схемы массива является метод compact, позволяющий
исключать нежелательные элементы до выполнения основной валидации.
При работе с пользовательскими данными массивы часто содержат «шум»:
null, undefined, пустые строки, некорректные
значения, оставшиеся после работы форм или API. Если такие элементы не
обработать заранее, они могут привести к ошибкам валидации или искажению
результатов проверок min, max, of
и других ограничений.
В Yup массив описывается через:
import * as Yup from 'yup';
const schema = Yup.array().of(
Yup.string()
);
Однако такой схемы недостаточно, если входные данные нестабильны и требуют предварительной фильтрации.
Метод compact предназначен для удаления элементов
массива по заданному правилу перед тем, как к нему применяются остальные
валидаторы.
Сигнатура:
array().compact(rejector?: (value, index, array) => boolean)
Поведение зависит от переданного аргумента:
rejector не указан — удаляются «пустые» значения
(аналогично поведению lodash.compact);rejector указан — удаляются элементы, для которых
функция возвращает true.Наиболее простой сценарий — очистка массива от falsy-значений:
const schema = Yup.array()
.compact()
.of(Yup.string());
В этом случае из массива будут исключены значения, которые
интерпретируются как ложные: undefined, null,
'', false, 0,
NaN.
После очистки оставшиеся элементы проходят стандартную проверку
of(Yup.string()).
Более гибкий вариант — передача функции-предиката:
const schema = Yup.array()
.compact((value) => value === null || value === undefined)
.of(Yup.number());
Здесь удаляются только null и undefined, а
остальные значения остаются без изменений.
Предикат получает доступ ко всем параметрам элемента:
(value, index, array) => boolean
Это позволяет строить более сложные условия:
const schema = Yup.array()
.compact((value, index) => index % 2 === 0)
.of(Yup.string());
В данном случае удаляются элементы с чётными индексами.
Важно понимать, что compact изменяет сам массив до
применения остальных правил схемы.
Например:
const schema = Yup.array()
.compact()
.min(3);
Если входной массив:
[1, null, 2, undefined, 3]
После compact:
[1, 2, 3]
Именно этот результат участвует в проверке min(3).
В Yup существует метод transform, который также
позволяет изменять входные данные, но его семантика отличается.
compact:
transform:
Пример эквивалента через transform:
array().transform((value) =>
value.filter((v) => v != null)
)
Однако compact является более декларативным и читаемым
решением именно для задачи очистки массива.
При построении схемы порядок методов имеет значение:
Yup.array()
.compact()
.of(Yup.string().required())
.min(1)
Логика выполнения:
compact;of(...);min, max,
length и т.д.).Если переставить вызовы, результат может измениться, особенно при
строгих ограничениях внутри of.
compact не ограничивается примитивами. При работе с
объектами фильтрация строится по ссылке на элемент:
const schema = Yup.array()
.compact((obj) => obj?.active === false)
.of(
Yup.object({
id: Yup.number().required(),
active: Yup.boolean()
})
);
Здесь исключаются все неактивные элементы до запуска валидации объектов.
Если после применения compact массив становится пустым,
дальнейшее поведение зависит от остальных правил:
Yup.array()
.compact()
.min(1, 'Минимум один элемент');
Вход:
[null, undefined]
После compact:
[]
Результат — ошибка min.
Фильтрация форм с динамическими полями:
const schema = Yup.array()
.compact()
.of(Yup.string().trim().min(1));
Очистка API-данных:
const schema = Yup.array()
.compact((v) => typeof v !== 'number')
.of(Yup.number());
Обработка списков с необязательными значениями:
const schema = Yup.array()
.compact()
.of(Yup.mixed());
compact не изменяет исходный массив напрямую в
пользовательском коде, но создаёт промежуточное преобразование внутри
схемы. Это означает, что оригинальные данные сохраняются вне контекста
Yup, однако внутренняя валидация работает уже с очищенной версией
массива.
При использовании сложных структур compact часто
применяется до глубоких проверок:
const schema = Yup.array()
.compact()
.of(
Yup.object({
name: Yup.string().required(),
age: Yup.number().min(0)
})
)
.required();
Это снижает нагрузку на валидацию вложенных схем за счёт предварительного удаления некорректных элементов.
compact работает только с массивами;