zod vs joi vs io-ts vs runtypes
データバリデーションライブラリ
zodjoiio-tsruntypes類似パッケージ:

データバリデーションライブラリ

データバリデーションライブラリは、JavaScriptやTypeScriptのアプリケーションでデータの整合性を確保するために使用されるツールです。これらのライブラリは、入力データが期待される形式や構造に従っているかどうかを検証し、エラーを防ぐための手段を提供します。特に、APIからのレスポンスやユーザー入力など、外部からのデータを扱う際に重要です。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
zod93,162,09942,1694.34 MB2922ヶ月前MIT
joi15,154,13521,199557 kB1924ヶ月前BSD-3-Clause
io-ts2,229,8176,818460 kB1621年前MIT
runtypes02,690312 kB271年前MIT

機能比較: zod vs joi vs io-ts vs runtypes

型安全性

  • zod:

    Zodは、TypeScriptの型推論を活用し、型安全なバリデーションを提供します。スキーマを定義する際に、型情報が自動的に推論されるため、開発者は型の整合性を簡単に保つことができます。

  • joi:

    Joiは、型安全性を提供しませんが、スキーマを定義することで、データの構造を明示的に示すことができます。TypeScriptを使用する場合は、別途型定義を行う必要があります。

  • io-ts:

    io-tsは、TypeScriptの型システムと統合されており、型安全なバリデーションを提供します。これにより、コンパイル時に型の整合性をチェックでき、ランタイムエラーを減少させることが可能です。

  • runtypes:

    Runtypesは、TypeScriptの型を利用して、型安全なバリデーションを提供します。型の定義とバリデーションが密接に関連しており、型の整合性を保ちながらデータを検証できます。

APIの使いやすさ

  • zod:

    Zodは、シンプルで直感的なAPIを提供し、特にTypeScriptとの統合がスムーズです。スキーマの定義が簡単で、迅速にバリデーションを行うことができます。

  • joi:

    Joiは、非常に直感的で使いやすいAPIを提供します。スキーマの定義が簡単で、柔軟なバリデーションルールを簡単に作成できます。

  • io-ts:

    io-tsは、型定義とバリデーションを統合するため、APIがやや複雑です。型を明示的に定義する必要があり、学習コストがかかる場合があります。

  • runtypes:

    Runtypesは、APIがシンプルで、TypeScriptの型を直接使用するため、使いやすさがあります。ただし、他のライブラリに比べて機能が限られる場合があります。

エラーメッセージのカスタマイズ

  • zod:

    Zodは、エラーメッセージのカスタマイズが容易で、各スキーマに対して独自のエラーメッセージを設定できます。これにより、ユーザーにとって分かりやすいエラーメッセージを提供できます。

  • joi:

    Joiは、エラーメッセージをカスタマイズするための豊富なオプションを提供しています。各バリデーションルールに対して、独自のエラーメッセージを設定できるため、ユーザーにとって理解しやすいメッセージを提供できます。

  • io-ts:

    io-tsは、エラーメッセージのカスタマイズが難しい場合があります。デフォルトのエラーメッセージが提供されますが、詳細なカスタマイズは手間がかかります。

  • runtypes:

    Runtypesは、エラーメッセージのカスタマイズが可能ですが、Joiほどの柔軟性はありません。基本的なエラーメッセージを提供しつつ、必要に応じてカスタマイズできます。

パフォーマンス

  • zod:

    Zodは、パフォーマンスが非常に高く、特にTypeScriptとの統合がスムーズです。バリデーションの速度が速く、大規模なデータセットに対しても効果的に機能します。

  • joi:

    Joiは、パフォーマンスが良好で、大規模なデータセットに対しても迅速にバリデーションを行うことができます。特に、スキーマのキャッシング機能がパフォーマンスを向上させます。

  • io-ts:

    io-tsは、型安全性を重視するため、バリデーションのパフォーマンスが他のライブラリに比べて劣る場合があります。特に、大規模なデータセットを扱う場合、パフォーマンスに影響を与える可能性があります。

  • runtypes:

    Runtypesは、比較的軽量で、パフォーマンスが良好です。TypeScriptの型を利用しているため、型チェックとバリデーションが効率的に行えます。

エコシステムとサポート

  • zod:

    Zodは、最近人気が高まっているライブラリで、特にTypeScriptとの親和性が高いです。活発なコミュニティと豊富なドキュメントがあり、サポートが充実しています。

  • joi:

    Joiは、広く使用されているライブラリであり、豊富なドキュメントとコミュニティサポートがあります。多くのプロジェクトで採用されているため、情報が豊富です。

  • io-ts:

    io-tsは、TypeScriptエコシステムに特化しており、型安全性を重視する開発者に支持されています。ただし、他のライブラリに比べてコミュニティが小さいため、情報が限られる場合があります。

  • runtypes:

    Runtypesは、比較的新しいライブラリですが、TypeScriptとの統合が強力で、徐々にコミュニティが成長しています。ドキュメントも充実してきています。

選び方: zod vs joi vs io-ts vs runtypes

  • zod:

    Zodは、シンプルさとパフォーマンスを重視したい場合に適しています。特に、TypeScriptとの親和性が高く、型推論が強力で、開発者にとって使いやすい選択肢です。

  • joi:

    Joiはシンプルで直感的なAPIを提供しており、迅速なプロトタイピングや小規模なアプリケーションに適しています。特に、スキーマ定義が簡単で、柔軟なバリデーションルールを作成したい場合におすすめです。

  • io-ts:

    TypeScriptを使用している場合、io-tsは型安全性を重視したいプロジェクトに最適です。型定義とバリデーションを統合できるため、型の整合性を保ちながらデータを検証できます。

  • runtypes:

    Runtypesは、TypeScriptの型システムを活用しつつ、ランタイムバリデーションを行いたい場合に適しています。型とバリデーションを明確に分離したい場合に選択すると良いでしょう。

zod のREADME

Zod logo

Zod

TypeScript-first schema validation with static type inference
by @colinhacks


Zod CI status License npm discord server stars

Docs   •   Discord   •   𝕏   •   Bluesky


Featured sponsor: Jazz

jazz logo

Learn more about featured sponsorships




Read the docs →



What is Zod?

Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.

import * as z from "zod";

const User = z.object({
  name: z.string(),
});

// some untrusted data...
const input = {
  /* stuff */
};

// the parsed result is validated and type safe!
const data = User.parse(input);

// so you can use it with confidence :)
console.log(data.name);

Features

  • Zero external dependencies
  • Works in Node.js and all modern browsers
  • Tiny: 2kb core bundle (gzipped)
  • Immutable API: methods return a new instance
  • Concise interface
  • Works with TypeScript and plain JS
  • Built-in JSON Schema conversion
  • Extensive ecosystem

Installation

npm install zod

Basic usage

Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.

import * as z from "zod";

const Player = z.object({
  username: z.string(),
  xp: z.number(),
});

Parsing data

Given any Zod schema, use .parse to validate an input. If it's valid, Zod returns a strongly-typed deep clone of the input.

Player.parse({ username: "billie", xp: 100 });
// => returns { username: "billie", xp: 100 }

Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you'll need to use the .parseAsync() method instead.

const schema = z.string().refine(async (val) => val.length <= 8);

await schema.parseAsync("hello");
// => "hello"

Handling errors

When validation fails, the .parse() method will throw a ZodError instance with granular information about the validation issues.

try {
  Player.parse({ username: 42, xp: "100" });
} catch (err) {
  if (err instanceof z.ZodError) {
    err.issues;
    /* [
      {
        expected: 'string',
        code: 'invalid_type',
        path: [ 'username' ],
        message: 'Invalid input: expected string'
      },
      {
        expected: 'number',
        code: 'invalid_type',
        path: [ 'xp' ],
        message: 'Invalid input: expected number'
      }
    ] */
  }
}

To avoid a try/catch block, you can use the .safeParse() method to get back a plain result object containing either the successfully parsed data or a ZodError. The result type is a discriminated union, so you can handle both cases conveniently.

const result = Player.safeParse({ username: 42, xp: "100" });
if (!result.success) {
  result.error; // ZodError instance
} else {
  result.data; // { username: string; xp: number }
}

Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you'll need to use the .safeParseAsync() method instead.

const schema = z.string().refine(async (val) => val.length <= 8);

await schema.safeParseAsync("hello");
// => { success: true; data: "hello" }

Inferring types

Zod infers a static type from your schema definitions. You can extract this type with the z.infer<> utility and use it however you like.

const Player = z.object({
  username: z.string(),
  xp: z.number(),
});

// extract the inferred type
type Player = z.infer<typeof Player>;

// use it in your code
const player: Player = { username: "billie", xp: 100 };

In some cases, the input & output types of a schema can diverge. For instance, the .transform() API can convert the input from one type to another. In these cases, you can extract the input and output types independently:

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

type MySchemaIn = z.input<typeof mySchema>;
// => string

type MySchemaOut = z.output<typeof mySchema>; // equivalent to z.infer<typeof mySchema>
// number