lenec ru

← все посты

Zod vs Valibot vs ArkType: чем валидировать

17K

Валидация — это место, где вкус разработчика встречается с реальными размерами бандла. У нас есть три актуальных кандидата: Zod, Valibot и ArkType. Все три — TypeScript-first, выводят типы из схем, работают в браузере и на сервере. Но устроены и ощущаются они по-разному. Я использовала каждый в проде и расскажу, что выбираю в каких сценариях.

Базовое сравнение

Zod — старший в семье, самый зрелый, самый популярный. Объектно-ориентированный API с цепочкой методов.

Valibot — относительно новый игрок, который делает упор на tree-shakeable функции. Размер схемы определяется тем, какие функции реально используются.

ArkType — синтаксически близкий к TypeScript: схемы пишутся почти как типы. Внутри — мощный движок с inference, недоступным в Zod и Valibot.

Zod: API и пример

import { z } from 'zod';

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  age: z.number().int().min(18).max(100),
  tags: z.array(z.string()).max(5).optional(),
  role: z.enum(['admin', 'user', 'guest']),
});

type User = z.infer<typeof UserSchema>;

const result = UserSchema.safeParse(unknownInput);
if (!result.success) {
  console.log(result.error.flatten());
} else {
  const user: User = result.data;
}

API очень дружелюбный. Цепочка методов читается легко. Огромное коммьюнити: интеграции с RHF, Hono, tRPC, Next.js — везде Zod считается дефолтом.

Valibot: API и пример

import * as v from 'valibot';

const UserSchema = v.object({
  id: v.pipe(v.string(), v.uuid()),
  email: v.pipe(v.string(), v.email()),
  age: v.pipe(v.number(), v.integer(), v.minValue(18), v.maxValue(100)),
  tags: v.optional(v.pipe(v.array(v.string()), v.maxLength(5))),
  role: v.picklist(['admin', 'user', 'guest']),
});

type User = v.InferOutput<typeof UserSchema>;

const result = v.safeParse(UserSchema, unknownInput);

API функциональный. Каждая операция — отдельная импортируемая функция. Это даёт tree-shaking: в бандл попадает только то, что реально используется.

ArkType: API и пример

import { type } from 'arktype';

const User = type({
  id: 'string',
  email: 'string.email',
  age: 'number.integer>=18&<=100',
  'tags?': 'string[]<=5',
  role: "'admin' | 'user' | 'guest'",
});

type UserType = typeof User.infer;

const result = User(unknownInput);
if (result instanceof type.errors) {
  console.log(result.summary);
}

Синтаксис уникальный — описание как строки в стиле TypeScript-типов. Кому-то нравится моментально, кому-то требует привыкания.

Размер бандла

  • Zod, минимальный пример (один объект из 3 полей): ~12 КБ gzip.
  • Valibot, тот же пример: ~3.5 КБ gzip.
  • ArkType, тот же пример: ~14 КБ gzip.

Valibot ощутимо легче. На клиентских проектах, где валидация нужна для одной формы и десятка полей, разница 8-10 КБ заметна.

На больших схемах размер сходится: Zod ~24 КБ, Valibot ~10-12 КБ, ArkType ~16-18 КБ.

Производительность

На моих бенчмарках (простая схема, 100 000 валидаций):

  • Zod: ~410 мс.
  • Valibot: ~280 мс.
  • ArkType: ~140 мс.

ArkType — самый быстрый за счёт компиляции схем в оптимизированные функции. На горячих путях (валидация запросов в API под нагрузкой) это ощутимо.

Полнота возможностей

Zod — самый полный набор. Discriminated unions, transform, refine, brand, lazy, recursive — всё из коробки.

Valibot — почти полный, но некоторые фичи (lazy, recursive) реализованы менее удобно. Discriminated unions работают, но через более явный API.

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

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

Zod: подробные ошибки с путями (['user', 'address', 'city']) и кодами. Удобно для UI-форм. Localization через ZodErrorMap.

Valibot: похожий формат, чуть менее богатые метаданные.

ArkType: компактные, но местами менее читаемые. Для UI-форм требует обработки.

Интеграции

Zod — везде. RHF, TanStack Form, tRPC, Hono, Next, Astro Actions — всё работает с Zod. Если ваш стек уже использует одну из этих библиотек — Zod ставится бесплатно.

Valibot — растёт. RHF, TanStack Form поддерживают через адаптеры. tRPC — нужны костыли.

ArkType — пока в догоняющих. Сообщество меньше, интеграций меньше.

TypeScript inference

Zod: почти всегда работает, но на сложных дискриминированных типах иногда возвращает any или слишком широкий тип.

Valibot: похожее поведение.

ArkType: лучшая инференция из трёх. Особенно блестит на дискриминированных union'ах и сложных условных типах. Если у вас сложная business-логика с типами — ArkType удивит в лучшую сторону.

Когда я беру Zod

  • Любой проект, где нужно «просто валидировать и больше не думать».
  • Стек с tRPC, RHF, Next App Router — всё уже подружено с Zod.
  • Команда не хочет учить новый API.

Это мой дефолт.

Когда я беру Valibot

  • Лендинг, маленькое SPA, мобильное приложение — там, где размер бандла критичен.
  • Edge-функции с холодным стартом — меньше парсинга, быстрее старт.
  • Schema используется только в одном месте — tree-shaking даёт максимум.

Когда я беру ArkType

  • API на Bun или Node с высоконагруженной валидацией.
  • Сложная типовая модель с дискриминированными union'ами и условными типами.
  • Команда любит TS и хочет «писать типы вместо схем».

Грабли в Zod

Производительность на больших схемах. Если ты валидируешь огромные структуры под нагрузкой, Zod становится бутылочным горлышком. Решение: либо ArkType, либо валидировать только то, что критично.

Schemas нельзя сериализовать. Если нужно отправить схему по сети (например, для динамической формы), Zod не умеет.

Грабли в Valibot

API меняется. Между минорными версиями переименовывали функции (v.string([v.email()])v.pipe(v.string(), v.email())). На больших проектах это значит периодические правки.

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

Грабли в ArkType

Кривая обучения. Синтаксис строк нужно держать в голове, и для сложных кейсов документации иногда не хватает.

Сообщество меньше. На StackOverflow ответов по edge-кейсам пока меньше.

В сухом остатке

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

Я в новом проекте обычно начинаю с Zod, потому что 90% случаев он закрывает идеально. Если позже выясняется, что бандл стал слишком тяжёлым или производительность валидации режет API — мигрирую на Valibot или ArkType. Это занимает день-два.

Что копать дальше

Все три библиотеки развиваются, и через год картина может поменяться. Поставьте все три на маленьком проекте, попробуйте написать схемы — синтаксис, ощущение от API, читаемость кода. Технический выбор часто проигрывает эстетическому: команда быстрее принимает то, что нравится.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.