Проверка по регулярному выражению

Валидация по регулярному выражению в библиотеке Yup применяется для строгого контроля формата строковых данных. Такой подход используется при проверке email-адресов, телефонных номеров, идентификаторов, паролей и любых других значений, структура которых может быть формализована через регулярные выражения.

Основной метод для работы с регулярными выражениями в строковых схемах — matches. Он позволяет задать шаблон и определить поведение при несоответствии.

Базовый синтаксис matches

import * as yup from 'yup';

const schema = yup.object({
  username: yup
    .string()
    .matches(/^[a-zA-Z0-9_]+$/, 'Недопустимые символы в имени пользователя')
});

В данном примере допускаются только латинские буквы, цифры и символ подчёркивания. Любой другой символ приводит к ошибке валидации.

Структура метода matches

Метод принимает три параметра:

matches(regex: RegExp, message?: string | function, options?: object)
  • regex — регулярное выражение, которому должна соответствовать строка
  • message — сообщение об ошибке или функция, возвращающая сообщение
  • options — дополнительные параметры поведения проверки

Пример с пользовательским сообщением

const schema = yup.object({
  code: yup
    .string()
    .matches(/^\d{6}$/, 'Код должен содержать ровно 6 цифр')
});

Здесь используется якорение ^ и $, что фиксирует строгую длину значения.

Использование флага excludeEmptyString

По умолчанию пустая строка проверяется регулярным выражением. В некоторых сценариях требуется игнорировать пустые значения:

const schema = yup.object({
  referral: yup
    .string()
    .matches(/^[A-Z0-9]{8}$/, {
      message: 'Неверный формат кода',
      excludeEmptyString: true
    })
});

При установке excludeEmptyString: true пустая строка не проходит проверку через регулярное выражение и обрабатывается другими правилами схемы.

Проверка email через регулярное выражение

Несмотря на наличие встроенного метода email, иногда требуется собственный шаблон:

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

const schema = yup.object({
  email: yup
    .string()
    .matches(emailRegex, 'Некорректный email-адрес')
});

Такой вариант используется в случаях, когда требуется упрощённая или кастомная проверка формата.

Сложные регулярные выражения

Валидация может включать многоуровневые условия. Например, пароль с обязательными требованиями:

const passwordSchema = yup.object({
  password: yup
    .string()
    .min(8, 'Минимальная длина — 8 символов')
    .matches(/[A-Z]/, 'Должна быть хотя бы одна заглавная буква')
    .matches(/[a-z]/, 'Должна быть хотя бы одна строчная буква')
    .matches(/[0-9]/, 'Должна быть хотя бы одна цифра')
    .matches(/[@$!%*?&]/, 'Должен быть хотя бы один специальный символ')
});

Каждое регулярное выражение проверяет отдельное правило, что упрощает диагностику ошибок.

Группировка условий через одно выражение

Иногда логика объединяется в единый шаблон:

const schema = yup.object({
  username: yup
    .string()
    .matches(
      /^(?=.{3,16}$)[a-zA-Z][a-zA-Z0-9_]*$/,
      'Имя пользователя должно быть 3–16 символов, начинаться с буквы и содержать только латиницу, цифры и "_"'
    )
});

Здесь используется конструкция (?=.{3,16}$) как проверка длины без отдельного метода min и max.

Использование функции для сообщения об ошибке

Сообщение может формироваться динамически:

const schema = yup.object({
  slug: yup
    .string()
    .matches(/^[a-z0-9-]+$/, (params) => {
      return `Значение "${params.value}" не соответствует формату slug`;
    })
});

Функция получает контекст валидации, включая текущее значение поля.

Инвертированная логика через отрицательные классы

Регулярные выражения позволяют исключать символы:

const schema = yup.object({
  input: yup
    .string()
    .matches(/^[^<>]+$/, 'Символы < и > запрещены')
});

Такой подход часто применяется для защиты от потенциально опасного ввода.

Проверка международных форматов

Регулярные выражения используются для локализованных данных:

const phoneSchema = yup.object({
  phone: yup
    .string()
    .matches(/^\+7\d{10}$/, 'Номер должен быть в формате +7XXXXXXXXXX')
});

В данном случае фиксируется конкретный национальный формат номера.

Совмещение matches с другими методами строк

Метод matches не заменяет другие проверки, а дополняет их:

const schema = yup.object({
  tag: yup
    .string()
    .required('Поле обязательно')
    .trim()
    .lowercase()
    .matches(/^[a-z0-9-]+$/, 'Недопустимый формат тега')
});

Порядок вызовов влияет на результат: преобразования применяются до проверки регулярным выражением.

Множественные совпадения и стратегия валидации

При нескольких matches каждое правило выполняется независимо. Ошибка возвращается при первом несоответствии, если не настроена альтернативная стратегия обработки.

const schema = yup.object({
  field: yup
    .string()
    .matches(/^[a-z]+$/, 'Только буквы')
    .matches(/^.{5,}$/, 'Минимум 5 символов')
});

В подобных конструкциях важно учитывать приоритет сообщений и порядок их расположения.

Опциональные значения и регулярные выражения

При работе с необязательными полями требуется контроль пустых значений:

const schema = yup.object({
  promoCode: yup
    .string()
    .notRequired()
    .matches(/^[A-Z0-9]{0,10}$/, 'Неверный формат промокода')
});

Регулярное выражение допускает пустую строку или значение до 10 символов.

Производительность сложных выражений

Регулярные выражения с большим количеством групп и проверок могут замедлять валидацию. В схемах Yup рекомендуется избегать чрезмерно вложенных конструкций и использовать разбиение логики на несколько matches, когда это упрощает чтение и снижает стоимость проверки.

Ошибки проектирования регулярных проверок

Типичные проблемы при использовании matches:

  • отсутствие якорей ^ и $, приводящее к частичным совпадениям
  • дублирование логики в нескольких выражениях
  • чрезмерная сложность одного регулярного выражения
  • игнорирование пустых строк при отсутствии required

Пример некорректного шаблона:

.matches(/[a-z]+/, 'Ошибка')

Такое выражение пропустит строку 123abc456, так как совпадение найдено внутри строки.

Корректный вариант:

.matches(/^[a-z]+$/, 'Ошибка')

Контроль формата через строгие шаблоны

Регулярные выражения позволяют задавать полностью детерминированные форматы:

const schema = yup.object({
  orderId: yup
    .string()
    .matches(/^ORD-\d{4}-[A-Z]{2}$/, 'Неверный формат заказа')
});

Такая схема фиксирует структуру идентификатора: префикс, числовую часть и буквенный суффикс.

Комбинирование с трансформациями

Перед проверкой регулярным выражением часто выполняется нормализация:

const schema = yup.object({
  email: yup
    .string()
    .transform((value) => value?.trim().toLowerCase())
    .matches(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'Неверный email')
});

Трансформация обеспечивает стабильность входных данных перед применением регулярного выражения.

Использование предопределённых шаблонов

Регулярные выражения часто выносятся в константы для повторного использования:

const DIGITS_ONLY = /^\d+$/;
const LATIN_ONLY = /^[a-zA-Z]+$/;

const schema = yup.object({
  pin: yup.string().matches(DIGITS_ONLY, 'Только цифры'),
  name: yup.string().matches(LATIN_ONLY, 'Только латиница')
});

Такой подход повышает читаемость и упрощает сопровождение схем валидации.