Superstruct — библиотека для валидации и структурирования данных в JavaScript и TypeScript, ориентированная на декларативное описание схем и строгую проверку входящих значений. Основная идея заключается в том, чтобы описывать форму данных в виде композиции примитивов и структур, а затем проверять соответствие этих данных заранее определённым правилам.
В основе подхода лежит понятие структуры — функции-валидатора, которая принимает значение и проверяет его соответствие определённой форме. Если значение соответствует ожиданиям, оно возвращается как валидное; если нет — формируется ошибка.
Такой подход позволяет отделить бизнес-логику от проверки данных, делая код предсказуемым и устойчивым к некорректному вводу.
Ключевая особенность — декларативность: вместо ручной проверки условий создаётся схема данных, которая описывает правила один раз и применяется повторно.
Библиотека предоставляет набор базовых валидаторов для простых типов данных:
Пример базовой проверки:
import { string, number, boolean, validate } from 'superstruct';
const schema = {
name: string(),
age: number(),
isActive: boolean(),
};
validate(
{ name: 'Alex', age: 30, isActive: true },
schema
);
Каждая структура представляет собой функцию, возвращающую валидатор с заданными правилами.
Одним из ключевых преимуществ является возможность комбинирования простых структур в более сложные.
Структура объекта описывает набор полей и их типы:
import { object, string, number } from 'superstruct';
const User = object({
name: string(),
age: number(),
});
Объект проверяется рекурсивно: каждое поле валидируется согласно своей структуре.
Для работы с коллекциями используется структура массива:
import { array, number } from 'superstruct';
const Numbers = array(number());
Каждый элемент массива проходит отдельную проверку.
Поддерживается логика альтернативных структур:
import { union, string, number } from 'superstruct';
const Value = union([string(), number()]);
Значение считается валидным, если соответствует хотя бы одному из вариантов.
Одной из сильных сторон является возможность создавать собственные валидаторы.
import { define } from 'superstruct';
const PositiveNumber = define('PositiveNumber', (value) => {
return typeof value === 'number' && value > 0;
});
Такая структура может использоваться как любой встроенный тип.
Функция validate возвращает результат проверки в виде
кортежа:
const [error, result] = validate(data, schema);
error содержит информацию о несоответствииresult содержит преобразованные или проверенные
данныеЕсли требуется выброс исключения, используется
assert-подобный подход:
import { assert } from 'superstruct';
assert(data, schema);
При несоответствии данных выбрасывается ошибка с подробным описанием пути до проблемного поля.
Одним из важных механизмов является трассировка ошибок. При вложенной структуре система указывает точное место нарушения:
Это делает отладку предсказуемой даже при глубоко вложенных структурах.
Существуют дополнительные инструменты для управления поведением проверок.
Позволяет сделать поле необязательным:
import { object, string, optional } from 'superstruct';
const Schema = object({
name: string(),
nickname: optional(string()),
});
Разрешает значение null:
import { nullable, string } from 'superstruct';
const MaybeString = nullable(string());
В некоторых случаях структура может не только проверять, но и приводить данные к нужному виду. Это позволяет использовать единый слой нормализации входных данных.
Пример — преобразование строки в число:
import { coerce, number, string } from 'superstruct';
const NumberFromString = coerce(number(), string(), (value) =>
parseFloat(value)
);
Такая схема полезна при обработке внешних API или пользовательского ввода.
Структуры можно переиспользовать и комбинировать:
const Address = object({
city: string(),
zip: string(),
});
const User = object({
name: string(),
address: Address,
});
Это позволяет строить масштабируемые модели данных без дублирования логики.
При необходимости валидация может учитывать внешний контекст, например зависимости между полями. Для этого используются пользовательские функции-валидаторы, где проверка выполняется на уровне всей структуры.
Пример:
import { refine, object, number } from 'superstruct';
const Range = object({
min: number(),
max: number(),
});
const ValidRange = refine(Range, (value) => {
return value.min <= value.max;
});
Подобные системы валидации применяются в ситуациях, где требуется строгий контроль входящих данных:
Особенность подхода заключается в том, что структура данных описывается один раз и используется как единый источник истины для проверки и преобразования.
Superstruct построена на функциональной модели без избыточной магии. Каждая структура — это чистая функция, что обеспечивает:
Валидация выполняется синхронно, что делает библиотеку подходящей для большинства прикладных сценариев, где важна скорость и детерминированность обработки данных.