Декораторы представляют собой структурный приём, позволяющий оборачивать функции и методы дополнительным поведением без изменения их исходной реализации. В задачах валидации данных они используются как слой, который предваряет выполнение основной логики и обеспечивает проверку входных параметров.
В экосистеме Validator.js декораторы применяются не как встроенный механизм библиотеки, а как паттерн интеграции, позволяющий расширять поведение функций проверки и централизовать правила валидации.
Ключевая идея заключается в разделении ответственности:
Функциональный декоратор — это функция высшего порядка, принимающая исходную функцию и возвращающая её модифицированную версию.
import validator from "validator";
function withValidation(rules) {
return function (fn) {
return function (...args) {
for (const rule of rules) {
const { validate, message } = rule;
if (!validate(...args)) {
throw new Error(message);
}
}
return fn.apply(this, args);
};
};
}
const isEmailValid = (email) => validator.isEmail(email);
const createUser = withValidation([
{
validate: (email) => isEmailValid(email),
message: "Некорректный email"
}
])(function (email, name) {
return { email, name };
});
В этом примере:
Декораторы могут накладываться друг на друга, формируя цепочку проверок.
const composeValidators = (...decorators) =>
(fn) =>
decorators.reduceRight((acc, decorator) => decorator(acc), fn);
const isNotEmpty = (value) => !validator.isEmpty(value);
const isEmail = (value) => validator.isEmail(value);
const validateNotEmpty = (fn) =>
(...args) => {
args.forEach((arg) => {
if (!isNotEmpty(arg)) throw new Error("Пустое значение");
});
return fn(...args);
};
const validateEmail = (fn) =>
(...args) => {
if (!isEmail(args[0])) throw new Error("Email некорректен");
return fn(...args);
};
const createAccount = composeValidators(
validateNotEmpty,
validateEmail
)(function (email, password) {
return { email, password };
});
В среде TypeScript декораторы позволяют привязывать валидацию к методам и свойствам класса. Это особенно полезно в архитектуре сервисов и контроллеров.
{
"compilerOptions": {
"experimentalDecorators": true
}
}
function ValidateEmail(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.value;
descriptor.value = function (email: string, ...args: any[]) {
if (!validator.isEmail(email)) {
throw new Error("Некорректный email");
}
return original.apply(this, [email, ...args]);
};
return descriptor;
}
class UserService {
@ValidateEmail
createUser(email: string, name: string) {
return { email, name };
}
}
Здесь Validator.js используется внутри декоратора как источник проверочной логики.
При работе с объектными моделями декораторы свойств позволяют описывать правила валидации декларативно.
function IsEmail(target: any, propertyKey: string) {
let value: string;
Object.defineProperty(target, propertyKey, {
get: () => value,
set: (newValue: string) => {
if (!validator.isEmail(newValue)) {
throw new Error(`Некорректное значение в поле ${propertyKey}`);
}
value = newValue;
}
});
}
class User {
@IsEmail
email: string;
constructor(email: string) {
this.email = email;
}
}
Такой подход делает валидацию неотъемлемой частью модели данных.
Библиотека Validator.js предоставляет набор функций, ориентированных на строковую валидацию:
Декораторы позволяют:
function Rule(validatorFn, message) {
return function (targetFn) {
return function (...args) {
if (!validatorFn(...args)) {
throw new Error(message);
}
return targetFn(...args);
};
};
}
Декораторы могут принимать параметры, что позволяет создавать гибкие схемы проверки.
function MinLength(min) {
return function (fn) {
return function (value, ...args) {
if (!validator.isLength(value, { min })) {
throw new Error(`Минимальная длина ${min}`);
}
return fn(value, ...args);
};
};
}
const saveUsername = MinLength(5)(function (username) {
return username;
});
В сложных системах декораторы формируют промежуточный слой между входными данными и бизнес-логикой:
Такая архитектура уменьшает связанность кода и повышает предсказуемость обработки данных.
Декораторы легко расширяются пользовательскими функциями, построенными поверх Validator.js.
const isStrongPassword = (password) =>
validator.isStrongPassword(password, {
minLength: 8,
minNumbers: 2
});
function StrongPassword(fn) {
return function (password, ...args) {
if (!isStrongPassword(password)) {
throw new Error("Пароль слишком слабый");
}
return fn(password, ...args);
};
}
Декораторы валидации часто используются в:
Их основная роль — стандартизация проверки данных перед выполнением логики, опираясь на возможности Validator.js и функциональные композиции.