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

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

В Zod проверка строки с помощью регулярного выражения выполняется через метод regex у строкового схемного типа:

import { z } from "zod";

const schema = z.string().regex(/^[a-z]+$/);

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

Метод regex принимает два аргумента:

z.string().regex(pattern, message?)
  • pattern — регулярное выражение JavaScript
  • message — опциональное сообщение об ошибке
const usernameSchema = z
  .string()
  .regex(/^[a-z0-9_]{3,16}$/, "Некорректное имя пользователя");

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

Валидация форматов данных

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

Телефонные номера

const phoneSchema = z
  .string()
  .regex(/^\+?[1-9]\d{1,14}$/, "Некорректный номер телефона");

Данный шаблон соответствует международному формату E.164 с допустимым начальным плюсом.

Почтовые индексы

const zipSchema = z.string().regex(/^\d{6}$/, "Индекс должен состоять из 6 цифр");

Простая валидация URL

Хотя Zod имеет встроенный .url(), регулярные выражения могут использоваться для ограниченных случаев:

const simpleUrl = z
  .string()
  .regex(/^https?:\/\/[^\s]+$/, "Некорректный URL");

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

Регулярные выражения в Zod часто комбинируются с контекстными сообщениями, которые уточняют причину ошибки:

const passwordSchema = z
  .string()
  .regex(
    /^(?=.*[A-Z])(?=.*\d)[A-Za-z\d]{8,}$/,
    "Пароль должен содержать минимум 8 символов, одну заглавную букву и одну цифру"
  );

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

Ограничения метода regex в Zod

Метод regex работает только с типом z.string(). Попытка применить его к другим типам данных приводит к ошибке на этапе выполнения схемы.

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

  • .email() для email-адресов
  • .url() для URL
  • .uuid() для UUID

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

Сочетание regex с другими валидаторами

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

const productCodeSchema = z
  .string()
  .min(5)
  .max(12)
  .regex(/^[A-Z0-9-]+$/);

Здесь одновременно задаются ограничения на длину и допустимые символы. Порядок вызовов не влияет на конечный результат, но влияет на читаемость логики.

Предобработка данных перед regex

Zod позволяет выполнять предварительное преобразование строки перед проверкой:

const normalizedSchema = z
  .string()
  .transform((val) => val.trim().toLowerCase())
  .regex(/^[a-z]+$/);

В этом случае регулярное выражение применяется уже к нормализованным данным. Это снижает количество ложных ошибок, вызванных пробелами или регистром.

Использование refine вместо regex

Хотя regex является удобным методом, в некоторых случаях используется refine для более сложной логики:

const schema = z.string().refine((val) => {
  const isValid = /^[a-z]+$/.test(val) && val.length > 3;
  return isValid;
}, {
  message: "Строка не соответствует правилам"
});

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

Многоуровневая валидация и суперпроверки

Для сложных случаев используется superRefine, позволяющий формировать несколько ошибок:

const schema = z.string().superRefine((val, ctx) => {
  if (!/[A-Z]/.test(val)) {
    ctx.addIssue({
      code: "custom",
      message: "Нет заглавной буквы"
    });
  }

  if (!/\d/.test(val)) {
    ctx.addIssue({
      code: "custom",
      message: "Нет цифры"
    });
  }
});

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

Unicode и особенности регулярных выражений

При работе с Unicode-данными важно учитывать флаги регулярных выражений, особенно u:

const nameSchema = z
  .string()
  .regex(/^[\p{L}\s]+$/u, "Недопустимые символы в имени");

Флаг u позволяет корректно обрабатывать символы национальных алфавитов, включая кириллицу и другие Unicode-буквы.

Без этого флага выражение может работать некорректно при обработке расширенных символов.

Частые ошибки при использовании regex в Zod

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

Другой тип ошибки — дублирование встроенной функциональности:

z.string().regex(/^[^@]+@[^@]+\.[^@]+$/);

Такой код лучше заменить на:

z.string().email();

Использование специализированных методов снижает риск некорректной валидации.

Производительность и регулярные выражения

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

Особенно проблемными являются выражения с:

  • вложенными квантификаторами
  • обратными ссылками
  • чрезмерной жадностью

Пример потенциально проблемного шаблона:

/^(a+)+$/

Такие конструкции следует избегать в прикладной валидации.

Композиция схем с regex

Регулярные выражения хорошо сочетаются с композиционным подходом Zod:

const baseString = z.string();

const alphaSchema = baseString.regex(/^[a-z]+$/);
const numericSchema = baseString.regex(/^\d+$/);

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

Практическое применение в доменной валидации

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

const orderIdSchema = z.string().regex(/^ORD-\d{6}$/);
const invoiceSchema = z.string().regex(/^INV-[A-Z]{2}-\d{4}$/);

Такие схемы фиксируют бизнес-форматы данных и предотвращают появление некорректных идентификаторов уже на уровне входных данных.

Итоговые особенности использования regex в Zod

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