Документирование схем

Документирование схем в YupResolver начинается с понимания того, что сама схема валидации — это не просто технический объект, а формализованное описание правил данных, которое должно оставаться читаемым, расширяемым и согласованным в рамках проекта. В связке с @hookform/resolvers/yup схема Yup становится центральным источником правды для валидации форм, и именно поэтому её структура требует системного подхода к документированию.

Любая схема Yup представляет собой дерево правил, где каждый узел описывает отдельное поле формы. Уже на уровне структуры важно закладывать читаемость:

import * as Yup from "yup";

export const userSchema = Yup.object({
  email: Yup.string()
    .email("Некорректный формат email")
    .required("Email обязателен"),

  password: Yup.string()
    .min(8, "Минимум 8 символов")
    .required("Пароль обязателен"),
});

Документирование здесь начинается с именования полей и явного описания ограничений. Каждое правило становится частью спецификации данных, поэтому цепочка методов Yup фактически выполняет роль декларативной документации.

Использование метаданных схем

Yup предоставляет механизм добавления вспомогательной информации через meta. Это позволяет расширять схему не только правилами валидации, но и описательными данными, полезными для генерации UI или автоматической документации.

const schema = Yup.object({
  username: Yup.string()
    .required("Обязательное поле")
    .meta({
      label: "Имя пользователя",
      description: "Уникальное имя, отображаемое в профиле",
      example: "john_doe",
    }),
});

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

Лейблы как элемент семантического описания

Метод label играет роль семантического идентификатора поля. Он заменяет техническое имя поля в сообщениях об ошибках, делая их частью самодокументируемой системы.

Yup.string()
  .label("Электронная почта")
  .email("Некорректный формат")
  .required("Поле обязательно");

Использование label особенно важно в больших формах, где единообразие сообщений снижает когнитивную нагрузку при сопровождении кода.

Централизация сообщений валидации

Документирование схем невозможно без управления текстами ошибок. Разнесённые по проекту строки сообщений приводят к фрагментации логики, поэтому применяется централизованный подход:

const messages = {
  required: "Поле обязательно для заполнения",
  email: "Введите корректный email адрес",
  minPassword: "Пароль должен содержать минимум 8 символов",
};

export const authSchema = Yup.object({
  email: Yup.string()
    .email(messages.email)
    .required(messages.required),

  password: Yup.string()
    .min(8, messages.minPassword)
    .required(messages.required),
});

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

Композиция схем как форма повторного документирования

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

const emailField = Yup.string()
  .email("Некорректный email")
  .required("Обязательное поле");

const passwordField = Yup.string()
  .min(8, "Минимум 8 символов")
  .required("Обязательное поле");

export const registerSchema = Yup.object({
  email: emailField,
  password: passwordField,
});

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

Типизация как часть документации схем

При использовании TypeScript схема Yup становится источником типов данных. Это позволяет связать документацию и контракт данных:

import * as Yup from "yup";

export const schema = Yup.object({
  id: Yup.number().required(),
  title: Yup.string().required(),
});

export type FormData = Yup.InferType<typeof schema>;

Инференс типов превращает схему в двойную документацию: она одновременно описывает правила и структуру данных на уровне компиляции.

Описание схем через describe

Метод describe() позволяет получить структурированное представление схемы. Это используется для генерации документации или анализа формы:

const schemaDescription = schema.describe();

Получаемый объект содержит дерево полей, их типы, ограничения и вложенность. Это делает возможным построение автоматических схем документации API форм.

Согласованность сообщений и бизнес-логики

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

Yup.string()
  .min(12, "Пароль должен содержать минимум 12 символов для безопасности")
  .required("Пароль обязателен");

В этом случае сообщение становится частью спецификации, а не просто пользовательской подсказкой.

Разделение схем по контекстам

В сложных приложениях схемы разделяются по доменам. Такой подход делает документацию более предсказуемой:

  • схемы авторизации
  • схемы профиля пользователя
  • схемы платежей
  • схемы административных форм
// auth.schema.js
export const loginSchema = Yup.object({
  email: Yup.string().required(),
  password: Yup.string().required(),
});

// profile.schema.js
export const profileSchema = Yup.object({
  firstName: Yup.string().required(),
  lastName: Yup.string().required(),
});

Каждый файл схемы становится самостоятельным модулем документации.

Документирование вложенных структур

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

const addressSchema = Yup.object({
  city: Yup.string().required(),
  zip: Yup.string().required(),
});

export const userSchema = Yup.object({
  name: Yup.string().required(),
  address: addressSchema,
  tags: Yup.array().of(Yup.string()),
});

Вложенные схемы должны оставаться автономными, чтобы их можно было переиспользовать и описывать отдельно.

Явное описание ограничений данных

Документация схем становится полноценной только при явном указании ограничений:

  • минимальные и максимальные значения
  • допустимые форматы
  • обязательность полей
  • зависимости между полями
Yup.number()
  .min(18, "Возраст должен быть не менее 18")
  .max(100, "Недопустимое значение возраста");

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

Поддержка расширяемости схем

При проектировании схем важно учитывать возможность их расширения без нарушения документации:

const baseUserSchema = Yup.object({
  email: Yup.string().required(),
});

export const extendedUserSchema = baseUserSchema.shape({
  role: Yup.string().required(),
});

Метод shape позволяет добавлять новые поля, сохраняя базовую структуру и её документированность.

Документирование условной логики

Сложные формы часто содержат условные зависимости:

Yup.object({
  hasPhone: Yup.boolean(),

  phone: Yup.string().when("hasPhone", {
    is: true,
    then: (schema) => schema.required("Телефон обязателен"),
    otherwise: (schema) => schema.notRequired(),
  }),
});

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

Единый стиль описания схем

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

  • одинаковые правила именования полей
  • единые сообщения ошибок
  • централизованные валидаторы
  • повторно используемые блоки

Это превращает Yup-схемы в формализованный слой спецификации данных, который одновременно выполняет роль документации, контракта и механизма валидации.