Валидация массивов в Superstruct строится вокруг базового принципа: структура описывает форму данных, а не их поведение. Массив рассматривается как контейнер, каждый элемент которого обязан соответствовать заданному правилу. Такой подход позволяет комбинировать простые структуры в сложные схемы без потери читаемости и предсказуемости.
Для описания массива используется функция array,
принимающая структуру элемента:
import { array, string } from 'superstruct'
const StringArray = array(string())
В этом случае валидным будет любой массив, состоящий исключительно из строк:
StringArray.assert(['a', 'b', 'c']) // ok
StringArray.assert(['a', 1]) // ошибка
Ключевой момент: проверка выполняется для каждого элемента последовательно, и первое несоответствие прерывает валидацию.
Superstruct предоставляет базовые структуры для примитивов:
string, number, boolean. Их можно
напрямую использовать внутри массива:
import { array, number } from 'superstruct'
const Numbers = array(number())
Такой подход особенно полезен для входных данных API, где ожидаются списки идентификаторов, значений или координат.
Часто массивы содержат не примитивы, а сложные структуры. В этом
случае элементом массива становится struct:
import { array, object, string, number } from 'superstruct'
const User = object({
id: number(),
name: string()
})
const Users = array(User)
Каждый объект внутри массива проверяется независимо:
Users.assert([
{ id: 1, name: 'Alex' },
{ id: 2, name: 'Maria' }
])
Если хотя бы один объект нарушает структуру, весь массив считается невалидным.
Часто требуется контролировать длину массива. Для этого используется
второй аргумент array, где задаются ограничения:
import { array, string } from 'superstruct'
const Tags = array(string(), {
min: 1,
max: 5
})
Здесь проверяется сразу два условия:
Такие ограничения особенно важны при работе с формами и пользовательским вводом.
Частный случай ограничения — требование наличия хотя бы одного элемента:
const NonEmptyStrings = array(string(), {
min: 1
})
Это эквивалентно более строгой проверке, исключающей пустые коллекции, которые часто становятся источником логических ошибок в приложениях.
Superstruct поддерживает произвольную глубину вложенности. Массив может содержать другие массивы:
const Matrix = array(array(number()))
Такая структура описывает двумерный массив чисел. Проверка проходит по каждому уровню вложенности отдельно.
Пример валидного значения:
Matrix.assert([
[1, 2],
[3, 4]
])
При этом несоответствие может возникнуть на любом уровне:
Matrix.assert([
[1, 2],
[3, 'x']
])
Ошибка будет зафиксирована в конкретном элементе вложенного массива.
Массивы могут содержать элементы разных типов через
union:
import { array, union, string, number } from 'superstruct'
const Mixed = array(union([string(), number()]))
Теперь допустимы строки и числа одновременно:
Mixed.assert([1, 'a', 2, 'b'])
Такая конструкция используется при работе с неоднородными данными, например результатами API или логами.
Базовые структуры можно дополнять логикой через refine,
создавая более строгие условия:
import { array, number, refine } from 'superstruct'
const Positive = refine(number(), 'Positive', (value) => value > 0)
const PositiveArray = array(Positive)
Теперь массив допускает только положительные числа:
PositiveArray.assert([1, 2, 3])
PositiveArray.assert([1, -2, 3]) // ошибка
При валидации массива ошибки привязываются к конкретному индексу элемента. Это позволяет точно локализовать проблему:
Это особенно важно при обработке больших структур, где поиск некорректного значения вручную был бы затруднителен.
Superstruct не допускает undefined как валидное
значение, если это явно не предусмотрено структурой:
const MaybeString = union([string(), null])
const List = array(MaybeString)
В этом случае допустимы только строки и null, но не
undefined.
Комбинирование массивов и объектов позволяет описывать реальные модели данных:
const Comment = object({
id: number(),
text: string()
})
const Post = object({
title: string(),
comments: array(Comment, { min: 0 })
})
Такая схема отражает типичную структуру API-ответа, где один объект содержит вложенный список сущностей.
Массив в Superstruct всегда рассматривается как:
Подход обеспечивает строгую типизацию на уровне выполнения и делает валидацию предсказуемой даже в глубоко вложенных данных