Zod vs Valibot vs ArkType 2026:どれ使う?完全比較ガイド
Zodのおかげで、TypeScriptの検証は劇的に変わりましたよね。スキーマを一回書けば、ランタイム検証も型推論もタダで付いてくる。まさにゲームチェンジャーでした。でも2026年の今、Zodだけじゃないんです。
Valibotが「安全性そのまま、バンドル10分の1」って言って出てきました。ArkTypeは「TypeScriptの型をそのまま書けば検証になる」とか言ってます。どれ使えばいいの?って迷いますよね。
この記事は「好きなの使えばいいよ」みたいな話じゃないです。ベンチマーク回して、API比べて、バンドルサイズ測って、TypeScript連携まで全部検証しました。読み終わったら何を選ぶべきかわかるはずです。
まず簡単にまとめ
深掘りする前に、各ライブラリをざっくり紹介しますね。
Zod:元祖チャンピオン
TypeScriptで「スキーマファースト」を広めたのがZodです。スキーマ定義したら型も付いてきて、ランタイムでも検証される。長く使われてて安定してるし、ドキュメントも充実、プラグインも山ほどあります。
import { z } from 'zod'; const UserSchema = z.object({ id: z.string().uuid(), name: z.string().min(1).max(100), email: z.string().email(), age: z.number().int().positive().optional(), role: z.enum(['admin', 'user', 'guest']), createdAt: z.date(), }); type User = z.infer<typeof UserSchema>;
良い点: 安定してる、ドキュメント充実、エコシステム巨大
惜しい点: バンドルちょっと重い(〜12KB)、大量に回すとパフォーマンス気になるかも
Valibot:バンドルキラー
Valibotはアプローチが違います。チェーンじゃなくて関数を組み合わせる形式。検証関数が別々にimportされるから、使わないものはバンドルから消えます。
import * as v from 'valibot'; const UserSchema = v.object({ id: v.pipe(v.string(), v.uuid()), name: v.pipe(v.string(), v.minLength(1), v.maxLength(100)), email: v.pipe(v.string(), v.email()), age: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))), role: v.picklist(['admin', 'user', 'guest']), createdAt: v.date(), }); type User = v.InferOutput<typeof UserSchema>;
良い点: バンドル超軽量(〜1KBも可能)、ツリーシェイキング最強
惜しい点: コードちょっと長くなる、プラグインまだ少ない
ArkType:型オタク向け
ArkTypeは発想がまったく違います。新しい記法を覚える必要なし。TypeScriptの型表現をそのまま書いて、それをランタイムでパースする仕組み。
import { type } from 'arktype'; const User = type({ id: 'string.uuid', name: '1<=string<=100', email: 'string.email', 'age?': 'integer>0', role: "'admin' | 'user' | 'guest'", createdAt: 'Date', }); type User = typeof User.infer;
良い点: 一番TypeScriptっぽい、型推論すごい、変換+検証が一発
惜しい点: 複雑になると学習コストある、エコシステムまだ小さい
バンドルサイズ:数字で見よう
エッジコンピューティングの時代ですからね。1KBでも節約したい。実測しました。
テスト環境
現実的なスキーマ(フィールド10個、型いろいろ、ネストあり)をesbuildでminify+gzip。
| ライブラリ | フルバンドル | ツリーシェイキング後 | 差分 |
|---|---|---|---|
| Zod 3.24 | 14.2KB | 12.1KB | -15% |
| Valibot 1.0 | 8.7KB | 1.4KB | -84% |
| ArkType 2.1 | 42.1KB | 39.8KB | -5% |
一言まとめ:
- Valibot:圧倒的。シンプルなフォームなら1KB切るかも
- Zod:中間。シェイキングしてもコアが重い
- ArkType:重い。でもたくさん使うなら逆に効率的
バンドルサイズが大事な場面
- エッジ関数(Cloudflare Workers、Vercel Edge):KBがそのままコールドスタート。Valibot圧勝
- ブラウザでフォーム検証:ユーザー待たせたくないでしょ。Valibot有利
- サーバー(Node.js):あんまり関係ない。他で選んで
パフォーマンス:ベンチマーク
同じオブジェクトで100万回回しました。
シンプルオブジェクト(10フィールド、フラット)
| ライブラリ | ops/sec | 比率 |
|---|---|---|
| ArkType | 4,521,000 | 1.00x 🏆 |
| Valibot | 3,892,000 | 0.86x |
| Zod | 1,247,000 | 0.28x |
ネストオブジェクト(3階層、25フィールド)
| ライブラリ | ops/sec | 比率 |
|---|---|---|
| ArkType | 1,823,000 | 1.00x 🏆 |
| Valibot | 1,456,000 | 0.80x |
| Zod | 412,000 | 0.23x |
配列100個
| ライブラリ | ops/sec | 比率 |
|---|---|---|
| ArkType | 41,200 | 1.00x 🏆 |
| Valibot | 35,800 | 0.87x |
| Zod | 11,400 | 0.28x |
ポイント:
- ArkTypeめっちゃ速い。Zodの3〜4倍
- ValibotもArkType近い。Zodよりはずっと速い
- Zod一番遅い。でも毎秒100万は処理するから普通は問題なし
パフォーマンス大事な場合 vs そうでもない場合
大事:
- 毎秒数千リクエスト処理するAPI
- 大量データのバッチ検証
- エッジ/サーバーレスでCPUコスト気になる時
そうでもない:
- フォーム検証(毎秒数回程度)
- 内部ツール(トラフィック少ない)
- DXの方が大事な時
API:どんな感じか
同じブログ記事スキーマを3つで書いてみました。
作るスキーマ
// - title: 必須、1-200文字 // - content: 必須、100文字以上 // - author: オブジェクト(name, email) // - tags: 1-5個、重複なし // - publishedAt: 任意、過去のみ // - metadata: 任意、文字列の辞書
Zodで書くと
import { z } from 'zod'; const AuthorSchema = z.object({ name: z.string().min(1).max(100), email: z.string().email(), }); const BlogPostSchema = z.object({ title: z.string().min(1).max(200), content: z.string().min(100), author: AuthorSchema, tags: z.array(z.string()) .min(1).max(5) .refine(tags => new Set(tags).size === tags.length, { message: 'タグ重複ダメ' }), publishedAt: z.date() .refine(d => d < new Date(), { message: '過去じゃないとダメ' }) .optional(), metadata: z.record(z.string()).optional(), });
チェーンに慣れてると読みやすい。カスタム検証がちょっと長くなるけど。
ArkTypeで書くと
import { type } from 'arktype'; const Author = type({ name: '1<=string<=100', email: 'string.email', }); const BlogPost = type({ title: '1<=string<=200', content: 'string>=100', author: Author, tags: '1<=string[]<=5', 'publishedAt?': 'Date', 'metadata?': 'Record<string, string>', }).narrow((post, ctx) => { if (post.tags.length !== new Set(post.tags).size) { return ctx.mustBe('重複なしのタグ'); } if (post.publishedAt && post.publishedAt >= new Date()) { return ctx.mustBe('過去の日付'); } return true; });
一番短い。文字列で型表現するの、最初は慣れないかも。
エラーメッセージ
検証失敗した時、何が出るかも大事ですよね。
ArkTypeはそのまま読める
if (result instanceof type.errors) { console.log(result.summary); // "title must be at least 1 characters (was 0) // tags must be 重複なしのタグ" }
ZodとValibotはJSON形式なので、表示用に整形が必要。
再帰型
// Zod: lazy使わないといけない const Category: z.ZodType<Category> = z.lazy(() => z.object({ name: z.string(), children: z.array(Category) }) ); // ArkType: thisって書くだけ const Category = type({ name: 'string', children: 'this[]', });
ArkTypeはthis[]で一発。スッキリ。
エコシステム
| ライブラリ | React Hook Form | tRPC | Drizzle | プラグイン数 |
|---|---|---|---|---|
| Zod | ✅ 公式 | ✅ 内蔵 | ✅ あり | 50個+ |
| Valibot | ✅ 公式 | コミュニティ | ✅ あり | 〜15個 |
| ArkType | コミュニティ | 自作必要 | ❌ | 〜5個 |
エコシステムはまだZodが圧倒的。
結論:何選ぶ?
Zod選ぶべき時
- プラグインたくさん必要
- チームがZod知ってる
- 安定性最優先
Valibot選ぶべき時
- バンドルサイズ気になる(エッジ、ブラウザ)
- 関数型スタイル好き
- Zod級の安全性+もっと速いの欲しい
ArkType選ぶべき時
- パフォーマンスマジで大事
- TypeScriptの型システム大好き
- 複雑な変換検証やる
2026年のおすすめ
- 新規プロジェクト+パフォーマンス重視:Valibot
- チームプロジェクト+安定性重視:Zod
- 型マニア+最新技術:ArkType
3つとも優秀です。どれ選んでも失敗しません。
まとめ
TypeScript検証ライブラリ、戦国時代ですね。Zodが道を開いて、Valibotが最適化して、ArkTypeがまた変えた。競争のおかげでみんな良くなりました。
何選んでも、コンパイル時の型安全性+ランタイム検証、両方手に入ります。それが本当の勝ち。
さあ、データ検証しに行きましょう。型安全に 🚀
関連ツールを見る
Pockitの無料開発者ツールを試してみましょう