Методы валидации: parse, safeParse, parseAsync

Метод parse в Zod представляет собой базовый механизм синхронной валидации данных. Его основная особенность заключается в строгом поведении: при несоответствии входных данных заданной схеме выполнение прерывается с выбросом исключения.

import { z } from "zod";

const schema = z.object({
  id: z.number(),
  name: z.string()
});

const data = schema.parse({
  id: 1,
  name: "Alice"
});

В случае корректного соответствия структуры результатом работы parse становится типизированный объект, приведённый к форме схемы. При нарушении условий возникает исключение ZodError, содержащее детализированную информацию о причинах сбоя.

Ключевая характеристика метода — fail-fast модель. Валидация прекращается сразу при обнаружении первой критической ошибки, если не включены дополнительные режимы сбора ошибок.


Поведение и механизм ошибок parse

При нарушении схемы Zod формирует структурированное исключение, включающее массив issues. Каждый элемент описывает конкретное несоответствие: путь до поля, тип ожидаемого значения и фактическое значение.

try {
  schema.parse({
    id: "not-a-number",
    name: "Alice"
  });
} catch (e) {
  console.log(e.issues);
}

Типичная структура ошибки включает:

  • path — путь к полю
  • message — текстовое описание
  • code — код типа ошибки
  • expected и received — ожидаемый и фактический типы

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


safeParse

Метод safeParse реализует альтернативную модель работы без исключений. Вместо выброса ошибки он возвращает объект результата, содержащий статус валидации.

const result = schema.safeParse({
  id: "invalid",
  name: "Alice"
});

Структура результата имеет вид:

{
  success: boolean,
  data?: T,
  error?: ZodError
}

Если данные корректны:

{
  success: true,
  data: { id: 1, name: "Alice" }
}

Если данные некорректны:

{
  success: false,
  error: ZodError
}

Такой подход исключает необходимость использования try/catch и делает поток обработки более предсказуемым.


Структура результата safeParse

Объект результата safeParse разделяется на два взаимоисключающих состояния.

Успешный сценарий:

  • success: true
  • присутствует поле data
  • отсутствует error

Ошибочный сценарий:

  • success: false
  • присутствует поле error
  • отсутствует data

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

const result = schema.safeParse(input);

if (result.success) {
  result.data;
} else {
  result.error.issues;
}

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


parseAsync

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

const schema = z.object({
  email: z.string().email().refine(async (val) => {
    return await checkEmailExists(val);
  })
});

const data = await schema.parseAsync({
  email: "user@example.com"
});

Возвращаемое значение — Promise, который либо резолвится валидированными данными, либо реджектится с ZodError.


Асинхронные проверки и ограничения parseAsync

Асинхронный режим становится необходимым при использовании:

  • refine с async-функциями
  • superRefine с асинхронной логикой
  • кастомных валидаторов с внешними запросами

При этом синхронный parse не способен корректно обработать такие сценарии, поскольку не поддерживает ожидание Promise.

Пример асинхронной логики:

const schema = z.string().refine(async (value) => {
  const exists = await database.find(value);
  return !exists;
});

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

await schema.parseAsync("test");

Сравнение моделей поведения методов

Различие трёх методов определяется не только синхронностью, но и стратегией обработки ошибок.

parse

  • синхронный
  • выбрасывает исключение
  • подходит для строгой валидации входных данных

safeParse

  • синхронный
  • возвращает результат-объект
  • исключает необходимость обработки исключений

parseAsync

  • асинхронный
  • возвращает Promise
  • поддерживает асинхронные проверки

Контроль потока выполнения при разных методах

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

safeParse сохраняет поток выполнения, позволяя агрегировать ошибки и обрабатывать их централизованно.

parseAsync вводит асинхронную модель, в которой валидация становится частью цепочки async/await, что важно при интеграции с внешними источниками данных.


Поведение при сложных схемах

В сложных объектах с вложенными структурами поведение методов сохраняет единый принцип:

const schema = z.object({
  user: z.object({
    id: z.number(),
    profile: z.object({
      email: z.string().email()
    })
  })
});

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

user.profile.email

При использовании safeParse этот же путь будет доступен внутри error.issues.

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


Обработка массивов и коллекций

Методы одинаково работают с массивами и коллекциями:

const schema = z.array(z.number());

schema.parse([1, 2, 3]);

При ошибке:

schema.safeParse([1, "invalid", 3]);

Результат содержит информацию о конкретном индексе массива:

path: [1]

Использование в цепочках преобразований

Валидация часто комбинируется с трансформациями:

const schema = z.string().transform((val) => val.length);

В таком случае:

  • parse возвращает уже преобразованное значение
  • safeParse возвращает преобразованное значение внутри data
  • parseAsync поддерживает асинхронные трансформации

Поведение при кастомных ошибках

При использовании refine и superRefine формируются пользовательские сообщения:

const schema = z.number().refine((val) => val > 10, {
  message: "Слишком маленькое значение"
});

Эти ошибки интегрируются в стандартную структуру ZodError, независимо от метода вызова.


Типовые сценарии выбора метода

  • строгая валидация входных параметров API — parse
  • обработка пользовательского ввода — safeParse
  • проверка с обращением к внешним данным — parseAsync

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