Библиотека validator.js построена вокруг набора
независимых функций, каждая из которых выполняет строго одну проверку:
строка является email, URL, числом, находится ли в диапазоне и т.д.
Реальная валидация данных в приложениях почти никогда не ограничивается
одной проверкой, поэтому ключевым механизмом становится
комбинирование валидаторов.
Комбинирование означает построение сложных правил из простых функций с использованием логических связок, композиции и переиспользуемых обёрток.
Каждый валидатор в validator.js возвращает булево
значение. Это позволяет использовать стандартные логические операторы
Jav * aScript:
import validator from 'validator';
const isValidEmail = (value) =>
validator.isEmail(value);
const isCorporateEmail = (value) =>
validator.isEmail(value) && value.endsWith('@company.com');
Здесь реализовано простое комбинирование через оператор
&&. Такая схема соответствует логике
AND-композиции, когда все условия должны быть
истинны.
Комбинирование часто начинается с предварительной обработки данных.
validator.js предоставляет функции нормализации, которые
удобно включать в цепочки.
const normalizeAndValidateEmail = (value) => {
const normalized = validator.normalizeEmail(value, {
gmail_remove_dots: true,
});
return validator.isEmail(normalized);
};
Такое разделение улучшает предсказуемость: сначала данные приводятся к единому виду, затем проверяются.
При усложнении логики целесообразно использовать функциональную композицию. Валидаторы становятся функциями высшего порядка.
const composeValidators = (...validators) => (value) =>
validators.every((fn) => fn(value));
const isNonEmpty = (v) => !validator.isEmpty(v);
const isEmail = (v) => validator.isEmail(v);
const validateEmail = composeValidators(isNonEmpty, isEmail);
Функция composeValidators реализует универсальный
механизм AND-композиции. Она позволяет собирать сложные правила из
независимых компонентов.
В validator.js отсутствует встроенный механизм
логического OR, поэтому он реализуется вручную:
const anyOf = (...validators) => (value) =>
validators.some((fn) => fn(value));
const isEmail = (v) => validator.isEmail(v);
const isPhone = (v) => validator.isMobilePhone(v);
const isEmailOrPhone = anyOf(isEmail, isPhone);
Такая конструкция используется для гибких форм ввода, где допустимы альтернативные форматы данных.
Валидация часто зависит от внешнего контекста, что требует расширенных схем комбинирования:
const isAdultUserEmail = (email, age) =>
age >= 18 && validator.isEmail(email);
Более универсальный подход — создание фабрик валидаторов:
const createEmailValidator = (domain) => (email) =>
validator.isEmail(email) && email.endsWith(domain);
const isCompanyEmail = createEmailValidator('@company.com');
Здесь комбинируются проверка формата и бизнес-логика.
Валидация часто строится как последовательность шагов: нормализация → очистка → проверка.
const pipeline = (...steps) => (value) =>
steps.reduce((acc, fn) => fn(acc), value);
const trim = (v) => validator.trim(v);
const escape = (v) => validator.escape(v);
const isLengthValid = (v) => validator.isLength(v, { min: 5 });
const validateUsername = pipeline(trim, escape, isLengthValid);
Такой подход делает процесс проверки предсказуемым и легко расширяемым.
validator.js легко интегрируется с пользовательскими
функциями:
const isNotBlacklisted = (value) => {
const blacklist = ['admin', 'root', 'test'];
return !blacklist.includes(value.toLowerCase());
};
const isValidUsername = (value) =>
validator.isAlphanumeric(value) && isNotBlacklisted(value);
Здесь комбинируется библиотечная проверка и прикладная логика.
При работе с формами или API часто требуется проверка нескольких полей одновременно:
const validateUser = (user) => ({
email: validator.isEmail(user.email),
password: validator.isStrongPassword(user.password),
age: validator.isInt(user.age.toString(), { min: 18 }),
});
Такой подход формирует структурированный результат, где каждая ошибка локализована по полю.
Комбинированные валидаторы могут возвращать не только булево значение, но и подробную информацию:
const validatePassword = (value) => {
const errors = [];
if (!validator.isLength(value, { min: 8 }))
errors.push('Минимальная длина 8 символов');
if (!/[A-Z]/.test(value))
errors.push('Нет заглавной буквы');
if (!/[0-9]/.test(value))
errors.push('Нет цифры');
return {
valid: errors.length === 0,
errors,
};
};
Такой формат позволяет комбинировать несколько проверок в единый результат, сохраняя детализацию причин.
Иногда валидаторы включаются динамически в зависимости от состояния данных:
const validate = (value, options) => {
let check = validator.isLength(value, { min: 3 });
if (options.strict) {
check = check && validator.isAlphanumeric(value);
}
return check;
};
Это позволяет строить адаптивные схемы проверки.
Для масштабируемых проектов создаются библиотеки валидаторов на основе композиции:
export const validators = {
email: (v) => validator.isEmail(v),
requiredEmail: (v) =>
!validator.isEmpty(v) && validator.isEmail(v),
username: composeValidators(
(v) => validator.isLength(v, { min: 3, max: 20 }),
validator.isAlphanumeric
),
};
Такая структура упрощает поддержку и стандартизирует правила валидации во всём приложении.
При глубокой композиции важно учитывать порядок выполнения. Более дешёвые проверки выполняются раньше:
const validate = (value) =>
!validator.isEmpty(value) &&
validator.isEmail(value) &&
validator.isLength(value, { max: 255 });
Ранний выход при неудачной проверке уменьшает количество операций.
Распространённая проблема — чрезмерное усложнение цепочек:
const validate = (v) =>
validator.isEmail(v) &&
validator.isLength(v, { min: 5 }) &&
someOtherCheck(v) &&
anotherCheck(v);
При росте количества условий такая конструкция становится трудно сопровождаемой. В подобных случаях целесообразно разбивать логику на именованные функции или использовать композиционные утилиты.
Комбинирование валидаторов формирует основу архитектуры проверки
данных. Простые функции validator.js превращаются в
строительные блоки, из которых собираются сложные бизнес-правила,
включая условные проверки, альтернативные сценарии и многоуровневую
фильтрацию данных.