Валидация данных в Superstruct построена вокруг строгого описания структур и детализированной информации о том, почему проверка не прошла. Основным элементом системы является специализированный объект ошибки, который содержит не только факт неудачи, но и полный контекст: где именно произошло нарушение, какое значение ожидалось и что было получено фактически.
При нарушении схемы данных Superstruct генерирует экземпляр
StructError. Это не просто сообщение об ошибке, а
структурированный объект, предназначенный для машинной обработки.
Ключевые свойства StructError:
"StructError", позволяющее однозначно идентифицировать тип
ошибкиОсобенность заключается в том, что StructError не
ограничивается одним нарушением. Он может агрегировать несколько проблем
в рамках одной проверки.
Каждая ошибка внутри структуры описывается через объект failure. Он содержит точную информацию о месте и характере нарушения.
Основные поля failure:
Пример логики формирования пути:
{
user: {
profile: {
age: "not a number"
}
}
}
В этом случае path будет:
["user", "profile", "age"]
Такой подход позволяет точно локализовать проблему даже в глубоко вложенных структурах.
Superstruct различает два важных понятия: path и
branch.
branch особенно полезен при рекурсивной валидации, когда
структура содержит вложенные объекты или массивы. Он позволяет
восстановить контекст без обращения к исходному объекту целиком.
Наиболее частый класс ошибок связан с несовпадением ожидаемого и фактического типа данных.
Типичные случаи:
В таких ситуациях type в failure указывает на ожидаемое
ограничение, например:
expected: "number"
received: "string"
Это делает диагностику предсказуемой и унифицированной.
Union-структуры (union([...])) проверяют значение по
нескольким альтернативным схемам. Ошибка возникает только в том случае,
если ни одна из веток не подошла.
Особенность таких ошибок заключается в агрегации:
Это позволяет понять, почему значение не соответствует ни одному из допустимых вариантов.
Refinement-ошибки возникают при использовании кастомных предикатов.
Пример логики:
refinementВ отличие от типовых ошибок, здесь важен не тип данных, а логическое условие, например:
StructError может содержать несколько независимых нарушений. Это
достигается за счёт ленивой генерации через failures().
Особенности поведения:
Такой подход позволяет получить полную картину состояния данных, а не останавливаться на первой ошибке.
Поле message в StructError обычно отражает первую
найденную проблему. Однако оно не является исчерпывающим источником
информации.
Приоритет формирования:
Полная диагностика всегда строится через failures(), а
не через message.
При сложных структурах возможна ситуация, когда одна ошибка содержит
вложенные StructError.
Это происходит при:
В таких случаях ошибка превращается в дерево, где каждый узел содержит собственные failures и контекст.
StructError содержит данные, которые не всегда напрямую сериализуются в JSON:
failures)Поэтому для передачи ошибок обычно используют преобразование:
При работе с результатами валидации ключевым становится не сам факт ошибки, а её структура:
Такой формат позволяет автоматически строить формы ошибок, логировать проблемы и выполнять диагностику без ручного разбора сообщений.