В Superstruct любая валидация строится вокруг композиции структур. Для строковых данных используется базовый примитив:
import { string } from "superstruct";
const Username = string();
Такое определение само по себе не накладывает ограничений, кроме
типа. Для email и URL этого недостаточно, поэтому используются
дополнительные ограничения: либо через встроенные структуры, либо через
композицию с pattern и refine.
Email — один из наиболее проблемных типов данных с точки зрения строгой валидации. Полная спецификация RFC 5322 слишком сложна для практического применения, поэтому в реальных проектах используется упрощённый, но достаточный для большинства случаев подход.
В некоторых версиях Superstruct доступны готовые валидаторы:
import { email } from "superstruct";
const Email = email();
Такая структура проверяет строку на соответствие типичному формату адреса электронной почты.
Использование:
import { assert } from "superstruct";
assert("user@example.com", Email); // проходит
assert("invalid-email", Email); // выбросит ошибку
Если требуется более строгий контроль или кастомизация, используется
pattern:
import { string, pattern } from "superstruct";
const Email = pattern(
string(),
/^[^\s@]+@[^\s@]+\.[^\s@]+$/
);
Этот вариант проверяет базовую структуру:
@Важно понимать, что даже такое выражение не охватывает всех допустимых email-форматов, но в большинстве веб-приложений этого достаточно.
Когда требуется более сложная логика, используется
refine:
import { string, refine } from "superstruct";
const Email = refine(string(), "Email", (value) => {
const basic = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
const noDoubleDots = !value.includes("..");
return basic && noDoubleDots;
});
Здесь добавлено дополнительное правило: запрет на последовательные точки.
Валидация часто сопровождается нормализацией. Например, приведение к нижнему регистру:
const normalizeEmail = (value) => value.trim().toLowerCase();
const Email = refine(string(), "Email", (value) => {
const normalized = normalizeEmail(value);
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalized);
});
URL-адреса имеют более сложную структуру, чем email, поскольку включают протокол, домен, путь, параметры и якоря.
В Superstruct может быть доступна готовая структура:
import { url } from "superstruct";
const Website = url();
Она проверяет корректность URL в стандартных схемах
(http, https и др.).
Наиболее надёжный способ — использование встроенного объекта
URL в Jav * aScript:
import { string, refine } from "superstruct";
const Website = refine(string(), "URL", (value) => {
try {
new URL(value);
return true;
} catch {
return false;
}
});
Преимущество этого подхода:
Часто требуется ограничить допустимые протоколы:
const Website = refine(string(), "URL", (value) => {
try {
const url = new URL(value);
return ["http:", "https:"].includes(url.protocol);
} catch {
return false;
}
});
Иногда требуется контроль домена:
const Website = refine(string(), "URL", (value) => {
try {
const url = new URL(value);
return url.hostname.includes(".");
} catch {
return false;
}
});
Более строгий вариант может проверять конкретные TLD:
const allowedTLD = ["com", "org", "net"];
const Website = refine(string(), "URL", (value) => {
try {
const url = new URL(value);
const tld = url.hostname.split(".").pop();
return allowedTLD.includes(tld);
} catch {
return false;
}
});
В реальных схемах email и URL часто используются вместе, например в профиле пользователя:
import { object, string, email, url } from "superstruct";
const User = object({
name: string(),
email: email(),
website: url(),
});
Такой подход позволяет централизованно описывать структуру данных и повторно использовать валидаторы.
Superstruct возвращает структурированные ошибки, которые можно использовать для диагностики:
import { validate } from "superstruct";
const [error, value] = validate("invalid-email", email());
if (error) {
console.log(error.failures());
}
Каждая ошибка содержит:
Для улучшения UX часто добавляют преобразование ошибок:
const formatErrors = (error) => {
return error.failures().map(f => ({
field: f.path.join("."),
message: "Некорректный формат значения",
}));
};
Superstruct позволяет сочетать валидацию и преобразование:
import { coerce, string, email } from "superstruct";
const Email = coerce(email(), string(), (value) =>
value.trim().toLowerCase()
);
Теперь входные данные автоматически нормализуются перед проверкой.
При работе с email и URL важно учитывать типичные ошибки:
Superstruct не заменяет безопасность приложения, но помогает отсеивать некорректные данные на входе.
Пример структуры формы регистрации:
import { object, string, email, url, optional } from "superstruct";
const Registration = object({
username: string(),
email: email(),
website: optional(url()),
referral: optional(string()),
});
Здесь:
При валидации массивов или объектов Superstruct проверяет каждое поле независимо:
const data = {
email: "bad-email",
website: "https://example.com",
};
Результат ошибки будет содержать только проблемное поле email, не блокируя анализ остальных данных.
При проектировании схем рекомендуется:
URL для проверки ссылок вместо regexrefine только для специфичных правилТакой подход делает систему предсказуемой и поддерживаемой даже при росте сложности проекта.