Length и matches для строк

Валидация строк в схемах Yup, используемых через YupResolver, опирается на набор базовых методов, среди которых ключевую роль играют ограничения длины и проверка соответствия шаблону. Эти инструменты позволяют формировать строгие правила для пользовательского ввода и обеспечивать предсказуемость данных на уровне формы ещё до отправки на сервер.


Работа с длиной строки в Yup реализуется через три основных метода: min, max и length. Каждый из них решает свою задачу, но в контексте резолвера используется одинаково — как часть схемы валидации формы.

min — минимальная длина строки

Метод min задаёт нижнюю границу допустимой длины строки. Это особенно важно для полей, где пустые или слишком короткие значения считаются невалидными.

import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";

const schema = Yup.object({
  username: Yup.string()
    .min(3, "Имя пользователя должно содержать минимум 3 символа")
});

При использовании через YupResolver это правило автоматически интегрируется в процесс валидации формы, например в React Hook Form.

const resolver = yupResolver(schema);

Любое значение короче трёх символов приведёт к ошибке, которая будет возвращена в структуре errors.


max — максимальная длина строки

Метод max ограничивает строку сверху. Это полезно для предотвращения переполнения базы данных, ограничения UI или соблюдения бизнес-логики.

const schema = Yup.object({
  nickname: Yup.string()
    .max(10, "Никнейм не может быть длиннее 10 символов")
});

При интеграции с YupResolver поведение остаётся декларативным: проверка выполняется автоматически при каждом изменении или сабмите формы (в зависимости от режима валидации).


length — точная длина строки

Метод length задаёт строго фиксированную длину строки. Это менее гибкий, но крайне полезный инструмент, особенно для кодов подтверждения, индексов или фиксированных идентификаторов.

const schema = Yup.object({
  code: Yup.string()
    .length(6, "Код должен состоять из 6 символов")
});

В отличие от комбинации min и max, length задаёт единственное допустимое значение длины, что делает схему более строгой и однозначной.


Сочетание ограничений длины

На практике часто требуется комбинировать ограничения, чтобы задать диапазон допустимых значений. Например:

const schema = Yup.object({
  password: Yup.string()
    .min(8, "Пароль слишком короткий")
    .max(32, "Пароль слишком длинный")
});

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

При использовании через YupResolver логика остаётся неизменной — резолвер лишь адаптирует Yup-схему к интерфейсу формы, не изменяя её поведение.


Сообщения об ошибках и их приоритет

Каждый метод (min, max, length) поддерживает кастомное сообщение ошибки. Важно учитывать, что при конфликтующих правилах порядок вызовов влияет на то, какая ошибка будет возвращена первой.

Yup.string()
  .min(5, "Минимум 5 символов")
  .max(10, "Максимум 10 символов")

Если строка имеет длину 3, сработает ошибка min, и проверка max не будет выполнена до устранения первой ошибки.


Проверка строк через matches (регулярные выражения)

Метод matches используется для проверки строки по регулярному выражению. Это один из самых гибких инструментов валидации, позволяющий описывать сложные шаблоны: email-подобные строки, номера телефонов, коды, форматы идентификаторов.

Базовое использование matches

const schema = Yup.object({
  username: Yup.string()
    .matches(/^[a-zA-Z0-9_]+$/, "Допустимы только буквы, цифры и символ '_'")
});

Здесь проверяется, что строка состоит только из латинских букв, цифр и подчёркивания.


matches с флагами и строгой проверкой

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

const schema = Yup.object({
  countryCode: Yup.string()
    .matches(/^[a-z]{2}$/i, "Код страны должен состоять из 2 букв")
});

Такая схема допускает ввод как ru, так и RU.


Использование matches для сложных форматов

Часто matches применяется для структурированных данных:

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

Здесь строго проверяется формат номера телефона.


Опциональная проверка и пустые строки

По умолчанию matches применяет проверку ко всем строкам, включая пустые. Это может приводить к неожиданным ошибкам при необязательных полях.

Решение — использовать nullable, notRequired или предварительную проверку:

const schema = Yup.object({
  middleName: Yup.string()
    .notRequired()
    .matches(/^[a-zA-Z]+$/, {
      message: "Только буквы",
      excludeEmptyString: true
    })
});

Параметр excludeEmptyString позволяет игнорировать пустые значения.


Комбинация length и matches

В реальных схемах часто возникает необходимость сочетать строгую длину и формат.

const schema = Yup.object({
  promoCode: Yup.string()
    .length(8, "Промокод должен содержать 8 символов")
    .matches(/^[A-Z0-9]+$/, "Только заглавные буквы и цифры")
});

Такая комбинация обеспечивает сразу два уровня контроля:

  • структурную целостность (длина)
  • синтаксическую корректность (формат)

Поведение через YupResolver в формах

При использовании YupResolver вся логика min, max, length и matches выполняется на уровне схемы Yup, а резолвер лишь преобразует результат в формат ошибок формы.

Типичный поток выглядит следующим образом:

  1. Пользователь вводит значение в поле
  2. Форма инициирует валидацию
  3. Yup выполняет проверки min/max/length/matches
  4. YupResolver преобразует ошибки в структуру errors
  5. UI отображает сообщения

Частые ошибки при использовании строковых ограничений

Перекрытие правил

Одновременное использование length и min/max на одной строке может привести к логическим конфликтам:

Yup.string()
  .length(5)
  .min(3) // избыточно

Фактически length уже фиксирует длину, и остальные ограничения становятся лишними.


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

Чрезмерно сложные matches могут снижать читаемость схемы. В таких случаях разумно выносить regex в константы:

const PHONE_REGEX = /^\+7\d{10}$/;

Yup.string().matches(PHONE_REGEX);

Пустые строки как валидное значение

Без явной настройки excludeEmptyString или notRequired пустые строки могут проваливать валидацию даже в необязательных полях.


Практическая структура схемы с длиной и matches

const schema = Yup.object({
  login: Yup.string()
    .min(4, "Минимум 4 символа")
    .max(20, "Максимум 20 символов")
    .matches(/^[a-zA-Z0-9_]+$/, "Недопустимые символы"),

  referralCode: Yup.string()
    .length(6, "Код должен быть 6 символов")
    .matches(/^[A-Z0-9]+$/, "Только заглавные буквы и цифры")
});

Такая структура показывает типичный подход: длина отвечает за границы, а matches — за форматирование данных.