Доступ к конкретным ошибкам

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

Каждый тест в Vest ассоциируется с конкретным полем (field). При провале проверки библиотека фиксирует сообщение ошибки внутри внутреннего состояния результата валидации.

Типичная структура ошибок выглядит как объект:

{
  username: ["Имя пользователя слишком короткое"],
  password: ["Пароль должен содержать минимум 8 символов"]
}

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

Получение ошибок по конкретному полю

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

import { create, test } from "vest";

const validate = create((data = {}) => {
  test("username", "USERNAME_REQUIRED", () => {
    if (!data.username) {
      return "Имя пользователя обязательно";
    }
  });

  test("username", "USERNAME_MIN_LENGTH", () => {
    if (data.username && data.username.length < 3) {
      return "Минимальная длина — 3 символа";
    }
  });
});

После выполнения:

const result = validate({ username: "ab" });

Доступ к ошибкам конкретного поля осуществляется через объект результата:

result.getErrors("username");

Возвращаемое значение:

["Минимальная длина — 3 символа"]

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

Использование getErrors для изолированного доступа

Метод getErrors(fieldName) является ключевым инструментом работы с частичными ошибками. Он возвращает только те сообщения, которые относятся к указанному полю.

Особенности поведения:

  • если поле не имеет ошибок — возвращается пустой массив
  • если поле не было задействовано в тестах — также возвращается пустой массив
  • порядок ошибок соответствует порядку выполнения тестов
const errors = result.getErrors("password");

При отсутствии ошибок:

[]

Это позволяет безопасно использовать результат без дополнительных проверок на undefined.

Доступ ко всем ошибкам и фильтрация

Полный объект ошибок доступен через:

result.errors

Пример структуры:

{
  username: ["Имя пользователя обязательно"],
  password: ["Пароль слишком короткий", "Пароль должен содержать цифру"]
}

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

const firstPasswordError = result.errors.password?.[0];

или безопасную деструктуризацию:

const { password = [] } = result.errors;

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

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

import { group, test, create } from "vest";

const validate = create(() => {
  group("auth", () => {
    test("email", "INVALID_EMAIL", () => {
      return "Некорректный email";
    });

    test("password", "WEAK_PASSWORD", () => {
      return "Слишком слабый пароль";
    });
  });
});

Результирующий доступ:

result.getErrors("email");

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

Доступ к первой ошибке поля

В реальных интерфейсах часто требуется не массив, а только первое сообщение. Vest не навязывает отдельный метод для этого, но предоставляет удобный способ извлечения:

const firstError = result.getErrors("username")[0];

или через результат:

const firstError = result.errors.username?.[0];

Такой подход применяется при отображении ошибок в UI под полем ввода.

Проверка наличия ошибок у конкретного поля

Для определения состояния поля используется проверка длины массива ошибок:

const hasUsernameError = result.getErrors("username").length > 0;

или:

const hasError = !!result.errors.username?.length;

Это важный механизм для динамического управления состоянием интерфейса.

Ошибки и приоритет тестов

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

test("password", "TOO_SHORT", () => "Слишком короткий");
test("password", "NO_NUMBER", () => "Нет цифры");

Результат:

["Слишком короткий", "Нет цифры"]

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

Частичный доступ при условной валидации

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

test("age", "AGE_REQUIRED", () => {
  if (!data.age) return "Возраст обязателен";
});

Если тест не выполняется, getErrors("age") возвращает пустой массив, а не null или undefined.

Использование ошибок в логике приложения

Доступ к конкретным ошибкам часто используется для:

  • отображения сообщений под конкретными полями
  • блокировки отправки формы
  • динамической подсветки UI-элементов
  • аналитики частых ошибок ввода

Пример блокировки отправки:

const result = validate(data);

if (result.hasErrors()) {
  if (result.getErrors("email").length) {
    // обработка ошибки email
  }
}

Безопасное извлечение ошибок

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

const message = result.errors?.username?.[0] || "";

Это предотвращает ошибки обращения к undefined и упрощает интеграцию в шаблонизаторы и UI-фреймворки.

Сравнение доступа через errors и getErrors

Использование errors:

result.errors.username
  • быстрый доступ
  • требует ручной проверки на существование

Использование getErrors:

result.getErrors("username")
  • всегда возвращает массив
  • безопасен для цепочек вызовов
  • предпочтителен для логики UI

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