https://zod.dev
静的タイプの推論を使用したTypeScript-Firstスキーマ検証
これらのドキュメントは中国語に翻訳されています。
npm
(ノード/パン)からdeno.land/x
から(デノ).shape
.keyof
.extend
.merge
.pick/.omit
.partial
.deepPartial
.required
.passthrough
.strict
.strip
.catchall
.element
.nonempty
.min/.max/.length
.parse
.parseAsync
.safeParse
.safeParseAsync
.refine
.superRefine
.transform
.default
.describe
.catch
.optional
.nullable
.nullish
.array
.promise
.or
.and
.brand
.readonly
.pipe
.pipe()
使用して、 z.coerce
の一般的な問題を修正できます。Zodは、タイプスクリプトファーストスキーマ宣言および検証ライブラリです。 「スキーマ」という用語を使用して、単純なstring
から複雑なネストされたオブジェクトまで、任意のデータ型を広く参照しています。
Zodは、開発者に可能な限り優れているように設計されています。目標は、重複型宣言を排除することです。 ZODを使用すると、バリデーターを一度宣言すると、ZODは静的タイプスクリプトタイプを自動的に推測します。より単純なタイプを複雑なデータ構造に構成するのは簡単です。
他のいくつかの素晴らしい側面:
.optional()
)新しいインスタンスを返しますあらゆるレベルのスポンサーシップは高く評価され、奨励されています。 ZODを使用して有料製品を構築した場合は、企業層の1つを検討してください。
最も包括的なユーザー管理プラットフォーム
clerk.com
|
|
|
|
|
Propelauth | セルボス | スカラー | Trigger.dev |
transloadit | 虚偽 | なんと | Cryptojobslist |
無地。 | その内容 | ストーリーブロック | マックス |
ブランドンバイエル | ジージ・ブラベック | アレックスヨハンソン | ファイブルシステム |
順応性 | アバナウォレット | ジェイソン・レンストーフ | Global Illumination、Inc。 |
マスターボーン | ライアン・パーマー | マイケル・スウィーニー | NextBase |
レモティ | コナー・シンノット | Mohammad-alia'râbi | スパトール |
ZODをネイティブにサポートするか、またはサポートするツールが増えています! ZODの上にツールまたはライブラリを作成した場合は、Twitterでそれについて教えてください。またはディスカッションを開始してください。以下に追加してツイートします。
tRPC
:graphqlなしでエンドツーエンドタイプフェーAPIを構築します。@anatine/zod-nestjs
:nestjsプロジェクトでzodを使用するためのヘルパーメソッド。zod-endpoints
:ZODを使用して、契約第一にタイプしたエンドポイント。 Openapi互換性。zhttp
:ZOD入力と応答の検証を備えたOpenAPI互換性のある、厳密にタイプされたHTTPライブラリ。domain-functions
:Composable関数を使用して、フレームワークからビジネスロジックを切り離します。 ZODスキーマを搭載したエンドからエンドへのエンドへの型推論を使用します。@zodios/core
:AxiosとZodに裏付けられたランタイムとコンパイル時間検証を備えたTypeScript APIクライアント。express-zod-api
:I/Oスキーマ検証とカスタムミドルウェアを使用して、ExpressベースのAPIをビルドします。tapiduck
:ZODとExpressを備えたエンドツーエンドのタイプフェーJSON API。 TRPCに少し似ていますが、よりシンプルです。koa-zod-router
:ZODを使用したI/O検証を使用して、KOAでTypeSafeルートを作成します。zod-sockets
:Zod-PoweredSocket.io I/O検証と組み込みのAsyncapi仕様を備えたMicroframework react-hook-form
:React HookフォームのファーストパーティZODリゾルバー。zod-validation-error
: ZodError
sからユーザーフレンドリーなエラーメッセージを生成します。zod-formik-adapter
:ZOD用のコミュニティが管理するFormikアダプター。react-zorm
:ZODを使用したReactのスタンドアロン<form>
生成と検証。zodix
:リミックスローダーとアクションのFormDataおよびURLSearchParamsのZODユーティリティ。conform
:HTMLフォームのプログレッシブ強化のためのTypeSafeフォーム検証ライブラリ。 Remixとnext.jsで動作しますremix-params-helper
:ZODと標準のurlsearchparamsおよびformdata for remixアプリの統合を簡素化します。formik-validator-zod
:formik-compliant validatorライブラリは、zodを使用してformikを使用して簡素化します。zod-i18n-map
:ZODエラーメッセージの翻訳に役立ちます。@modular-forms/solid
:検証のためにZODをサポートするSOLIDJのモジュラーフォームライブラリ。houseform
:検証にZodを使用するReactフォームライブラリ。sveltekit-superforms
:zod検証を備えたSveltekit用のスーパーチャージフォームライブラリ。mobx-zod-form
:Mobx&Zodに基づくデータファーストフォームビルダー。@vee-validate/zod
:zodスキーマ検証を備えたVue.jsのフォームライブラリ。zod-form-renderer
:Zodスキーマの自動インファーフォームフィールドと、E2Eタイプの安全性を備えたReact-Hook-Formでそれらをレンダリングします。 zod-to-ts
:ZODスキーマからタイプスクリプト定義を生成します。zod-to-json-schema
:ZODスキーマをJSONスキーマに変換します。@anatine/zod-openapi
:zodスキーマをOpenapi v3.x SchemaObject
に変換します。zod-fast-check
:Zodスキーマからfast-check
仲裁を生成します。zod-dto
:zodスキーマからnest.js dtosを生成します。fastify-type-provider-zod
:ZODスキーマからファーストタイププロバイダーを作成します。zod-to-openapi
: Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters.nestjs-graphql-zod
:ZODスキーマからNestJS GraphQLモデルクラスを生成します。 ZODスキーマで動作するGraphQLメソッドデコレータを提供します。zod-openapi
:Zodスキーマから完全なOpenapi V3.xドキュメントを作成します。fastify-zod-openapi
:ZODスキーマのFustifyタイププロバイダー、検証、シリアル化、 @Fastify/Swaggerサポート。typeschema
:スキーマ検証用のユニバーサルアダプター。zodex
:( de)zodスキーマのシリアル化ts-to-zod
:タイプスクリプトの定義をZODスキーマに変換します。@runtyping/zod
:静的タイプとjsonスキーマからzodを生成します。json-schema-to-zod
:JSONスキーマをZODスキーマに変換します。ライブデモ。json-to-zod
:JSONオブジェクトをZODスキーマに変換します。ライブデモ。graphql-codegen-typescript-validation-schema
:GraphQLコードジェネレータープラグインして、GraphQLスキーマからフォーム検証スキーマを生成します。zod-prisma
:PrismaスキーマからZODスキーマを生成します。Supervillain
:GO構造体からZODスキーマを生成します。prisma-zod-generator
:PrismaスキーマからZODスキーマをエミットします。drizzle-zod
:DrizzleスキーマからZODスキーマをエミットします。prisma-trpc-generator
:ZODを使用して、完全に実装されたTRPCルーターとその検証スキーマをエミットします。zod-prisma-types
PrismaモデルからZODタイプを作成します。quicktype
:JSONオブジェクトとJSONスキーマをZODスキーマに変換します。@sanity-typed/zod
:Sanity SchemasからZodスキーマを生成します。java-to-zod
:PojosをZodスキーマに変換しますOrval
:OpenapiスキーマからZODスキーマを生成しますKubb
:OpenapiスキーマからSDKとZODスキーマを生成します@anatine/zod-mock
:zodスキーマからモックデータを生成します。 faker.jsを搭載しています。zod-mocking
:ZODスキーマからモックデータを生成します。zod-fixture
:ZODスキーマを使用して、非関連性テストフィクスチャの生成を決定的な方法で自動化します。zocker
:スキーマからもっともらしいモックダタを生成します。zodock
Zodスキーマに基づいて模擬データを生成します。zod-schema-faker
Zodスキーマからモックデータを生成します。 @faker-js/fakerおよびrandexp.jsを搭載していますfreerstore
:Firestoreコストオプティマイザー。slonik
:node.jsは、強力なZOD統合を備えたクライアントをポストグレスします。schemql
:RAW SQLとターゲットタイプの安全性とスキーマ検証を組み合わせることにより、SQLワークフローを強化します。soly
:ZODでCLIアプリケーションを作成します。pastel
:React、Zod、およびインクを使用してCLIアプリケーションを作成します。zod-xlsx
:ZODスキーマを使用したXLSXベースのリソースバリーター。znv
:ZODスキーマを使用したnode.jsのタイプセーフ環境の解析と検証。zod-config
: Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.unplugin-environment
: A plugin for loading enviroment variables safely with schema validation, simple with virtual module, type-safe with intellisense, and better DX ?. ZODを搭載。 zod_utilz
:ZODのフレームワークアゴーシスユーティリティ。zod-playground
:ZODスキーマ検証機能を学習およびテストするためのツール。リンク。zod-sandbox
:ZODスキーマをテストするための制御環境。ライブデモ。zod-dev
:ZODランタイムのプロダクションを条件付きで無効にします。zod-accelerator
:Zodのスループットを最大100倍まで加速します。 タイプスクリプト4.5+!
tsconfig.json
でstrict
モードを有効にする必要があります。これは、すべてのタイプスクリプトプロジェクトのベストプラクティスです。
// tsconfig.json
{
// ...
"compilerOptions" : {
// ...
"strict" : true
}
}
npm
(ノード/パン)からnpm install zod # npm
yarn add zod # yarn
bun add zod # bun
pnpm add zod # pnpm
Zodは、すべてのコミットでカナリアバージョンも公開しています。カナリアをインストールするには:
npm install zod@canary # npm
yarn add zod@canary # yarn
bun add zod@canary # bun
pnpm add zod@canary # pnpm
deno.land/x
から(デノ)ノードとは異なり、DenoはNPMのようなパッケージマネージャーではなく、直接URLインポートに依存しています。 Zodはdeno.land/xで入手できます。最新のバージョンは、次のようにインポートできます。
import { z } from "https://deno.land/x/zod/mod.ts" ;
特定のバージョンを指定することもできます。
import { z } from "https://deno.land/x/[email protected]/mod.ts" ;
このREADMEの残りの部分は、NPMを使用し、
"zod"
パッケージから直接インポートすることを前提としています。
シンプルな文字列スキーマを作成します
import { z } from "zod" ;
// creating a schema for strings
const mySchema = z . string ( ) ;
// parsing
mySchema . parse ( "tuna" ) ; // => "tuna"
mySchema . parse ( 12 ) ; // => throws ZodError
// "safe" parsing (doesn't throw error if validation fails)
mySchema . safeParse ( "tuna" ) ; // => { success: true; data: "tuna" }
mySchema . safeParse ( 12 ) ; // => { success: false; error: ZodError }
オブジェクトスキーマの作成
import { z } from "zod" ;
const User = z . object ( {
username : z . string ( ) ,
} ) ;
User . parse ( { username : "Ludwig" } ) ;
// extract the inferred type
type User = z . infer < typeof User > ;
// { username: string }
import { z } from "zod" ;
// primitive values
z . string ( ) ;
z . number ( ) ;
z . bigint ( ) ;
z . boolean ( ) ;
z . date ( ) ;
z . symbol ( ) ;
// empty types
z . undefined ( ) ;
z . null ( ) ;
z . void ( ) ; // accepts undefined
// catch-all types
// allows any value
z . any ( ) ;
z . unknown ( ) ;
// never type
// allows no values
z . never ( ) ;
Zodは、原始値を強制するためのより便利な方法を提供するようになりました。
const schema = z . coerce . string ( ) ;
schema . parse ( "tuna" ) ; // => "tuna"
schema . parse ( 12 ) ; // => "12"
During the parsing step, the input is passed through the String()
function, which is a JavaScript built-in for coercing data into strings.
schema . parse ( 12 ) ; // => "12"
schema . parse ( true ) ; // => "true"
schema . parse ( undefined ) ; // => "undefined"
schema . parse ( null ) ; // => "null"
返されたスキーマは通常のZodString
インスタンスであるため、すべての文字列メソッドを使用できます。
z . coerce . string ( ) . email ( ) . min ( 5 ) ;
強制の仕組み
すべての原始タイプは強制をサポートします。 Zodは、組み込みのコンストラクターを使用してすべての入力を強制します: String(input)
、 Number(input)
、 new Date(input)
など。
z . coerce . string ( ) ; // String(input)
z . coerce . number ( ) ; // Number(input)
z . coerce . boolean ( ) ; // Boolean(input)
z . coerce . bigint ( ) ; // BigInt(input)
z . coerce . date ( ) ; // new Date(input)
注- z.coerce.boolean()
とのブールの強制は、あなたがどのように期待するかが機能しない場合があります。真実の価値はtrue
に強制され、偽りの値はfalse
に強制されます。
const schema = z . coerce . boolean ( ) ; // Boolean(input)
schema . parse ( "tuna" ) ; // => true
schema . parse ( "true" ) ; // => true
schema . parse ( "false" ) ; // => true
schema . parse ( 1 ) ; // => true
schema . parse ( [ ] ) ; // => true
schema . parse ( 0 ) ; // => false
schema . parse ( "" ) ; // => false
schema . parse ( undefined ) ; // => false
schema . parse ( null ) ; // => false
強制ロジックをさらに制御するには、 z.preprocess
またはz.pipe()
の使用を検討してください。
リテラルスキーマは、 "hello world"
または5
などの文字通りのタイプを表しています。
const tuna = z . literal ( "tuna" ) ;
const twelve = z . literal ( 12 ) ;
const twobig = z . literal ( 2n ) ; // bigint literal
const tru = z . literal ( true ) ;
const terrificSymbol = Symbol ( "terrific" ) ;
const terrific = z . literal ( terrificSymbol ) ;
// retrieve literal value
tuna . value ; // "tuna"
現在、ZODの日付リテラルのサポートはありません。この機能のユースケースがある場合は、問題を提出してください。
ZODには、一握りの文字列固有の検証が含まれています。
// validations
z . string ( ) . max ( 5 ) ;
z . string ( ) . min ( 5 ) ;
z . string ( ) . length ( 5 ) ;
z . string ( ) . email ( ) ;
z . string ( ) . url ( ) ;
z . string ( ) . emoji ( ) ;
z . string ( ) . uuid ( ) ;
z . string ( ) . nanoid ( ) ;
z . string ( ) . cuid ( ) ;
z . string ( ) . cuid2 ( ) ;
z . string ( ) . ulid ( ) ;
z . string ( ) . regex ( regex ) ;
z . string ( ) . includes ( string ) ;
z . string ( ) . startsWith ( string ) ;
z . string ( ) . endsWith ( string ) ;
z . string ( ) . datetime ( ) ; // ISO 8601; by default only `Z` timezone allowed
z . string ( ) . ip ( ) ; // defaults to allow both IPv4 and IPv6
// transforms
z . string ( ) . trim ( ) ; // trim whitespace
z . string ( ) . toLowerCase ( ) ; // toLowerCase
z . string ( ) . toUpperCase ( ) ; // toUpperCase
// added in Zod 3.23
z . string ( ) . date ( ) ; // ISO date format (YYYY-MM-DD)
z . string ( ) . time ( ) ; // ISO time format (HH:mm:ss[.SSSSSS])
z . string ( ) . duration ( ) ; // ISO 8601 duration
z . string ( ) . base64 ( ) ;
改良と組み合わせて使用できる他の便利な文字列検証関数については、validator.jsをチェックしてください。
文字列スキーマを作成するときに、いくつかの一般的なエラーメッセージをカスタマイズできます。
const name = z . string ( {
required_error : "Name is required" ,
invalid_type_error : "Name must be a string" ,
} ) ;
検証方法を使用する場合、追加の引数を渡してカスタムエラーメッセージを提供できます。
z . string ( ) . min ( 5 , { message : "Must be 5 or more characters long" } ) ;
z . string ( ) . max ( 5 , { message : "Must be 5 or fewer characters long" } ) ;
z . string ( ) . length ( 5 , { message : "Must be exactly 5 characters long" } ) ;
z . string ( ) . email ( { message : "Invalid email address" } ) ;
z . string ( ) . url ( { message : "Invalid url" } ) ;
z . string ( ) . emoji ( { message : "Contains non-emoji characters" } ) ;
z . string ( ) . uuid ( { message : "Invalid UUID" } ) ;
z . string ( ) . includes ( "tuna" , { message : "Must include tuna" } ) ;
z . string ( ) . startsWith ( "https://" , { message : "Must provide secure URL" } ) ;
z . string ( ) . endsWith ( ".com" , { message : "Only .com domains allowed" } ) ;
z . string ( ) . datetime ( { message : "Invalid datetime string! Must be UTC." } ) ;
z . string ( ) . date ( { message : "Invalid date string!" } ) ;
z . string ( ) . time ( { message : "Invalid time string!" } ) ;
z . string ( ) . ip ( { message : "Invalid IP address" } ) ;
ご存知かもしれませんが、Zod文字列にはいくつかの日付/時刻関連の検証が含まれています。これらの検証は正規表現に基づいているため、完全な日付/時刻ライブラリほど厳格ではありません。ただし、ユーザーの入力を検証するのに非常に便利です。
z.string().datetime()
メソッドはISO 8601を強制します。デフォルトは、タイムゾーンのオフセットと任意の小数の小数の精度ではありません。
const datetime = z . string ( ) . datetime ( ) ;
datetime . parse ( "2020-01-01T00:00:00Z" ) ; // pass
datetime . parse ( "2020-01-01T00:00:00.123Z" ) ; // pass
datetime . parse ( "2020-01-01T00:00:00.123456Z" ) ; // pass (arbitrary precision)
datetime . parse ( "2020-01-01T00:00:00+02:00" ) ; // fail (no offsets allowed)
タイムゾーンオフセットは、 offset
オプションをtrue
に設定することで許可できます。
const datetime = z . string ( ) . datetime ( { offset : true } ) ;
datetime . parse ( "2020-01-01T00:00:00+02:00" ) ; // pass
datetime . parse ( "2020-01-01T00:00:00.123+02:00" ) ; // pass (millis optional)
datetime . parse ( "2020-01-01T00:00:00.123+0200" ) ; // pass (millis optional)
datetime . parse ( "2020-01-01T00:00:00.123+02" ) ; // pass (only offset hours)
datetime . parse ( "2020-01-01T00:00:00Z" ) ; // pass (Z still supported)
さらに、許容precision
を制約できます。デフォルトでは、任意のサブセカンド精度がサポートされています(ただし、オプション)。
const datetime = z . string ( ) . datetime ( { precision : 3 } ) ;
datetime . parse ( "2020-01-01T00:00:00.123Z" ) ; // pass
datetime . parse ( "2020-01-01T00:00:00Z" ) ; // fail
datetime . parse ( "2020-01-01T00:00:00.123456Z" ) ; // fail
ZOD 3.23に追加されました
z.string().date()
メソッドは、形式の文字列を検証しますYYYY-MM-DD
。
const date = z . string ( ) . date ( ) ;
date . parse ( "2020-01-01" ) ; // pass
date . parse ( "2020-1-1" ) ; // fail
date . parse ( "2020-01-32" ) ; // fail
ZOD 3.23に追加されました
z.string().time()
メソッドは、形式で文字列を検証しますHH:MM:SS[.s+]
。 2番目には、任意の10進精度を含めることができます。それはいかなる種類のタイムゾーンのオフセットを許可しません。
const time = z . string ( ) . time ( ) ;
time . parse ( "00:00:00" ) ; // pass
time . parse ( "09:52:31" ) ; // pass
time . parse ( "23:59:59.9999999" ) ; // pass (arbitrary precision)
time . parse ( "00:00:00.123Z" ) ; // fail (no `Z` allowed)
time . parse ( "00:00:00.123+02:00" ) ; // fail (no offsets allowed)
許容される小数の精度を制約するために、 precision
オプションを設定できます。
const time = z . string ( ) . time ( { precision : 3 } ) ;
time . parse ( "00:00:00.123" ) ; // pass
time . parse ( "00:00:00.123456" ) ; // fail
time . parse ( "00:00:00" ) ; // fail
z.string().ip()
メソッドは、デフォルトでIPv4とIPv6を検証します。
const ip = z . string ( ) . ip ( ) ;
ip . parse ( "192.168.1.1" ) ; // pass
ip . parse ( "84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003" ) ; // pass
ip . parse ( "84d5:51a0:9114:1855:4cfa:f2d7:1f12:192.168.1.1" ) ; // pass
ip . parse ( "256.1.1.1" ) ; // fail
ip . parse ( "84d5:51a0:9114:gggg:4cfa:f2d7:1f12:7003" ) ; // fail
さらに、IP version
を設定できます。
const ipv4 = z . string ( ) . ip ( { version : "v4" } ) ;
ipv4 . parse ( "84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003" ) ; // fail
const ipv6 = z . string ( ) . ip ( { version : "v6" } ) ;
ipv6 . parse ( "192.168.1.1" ) ; // fail
番号スキーマを作成するときに、特定のエラーメッセージをカスタマイズできます。
const age = z . number ( {
required_error : "Age is required" ,
invalid_type_error : "Age must be a number" ,
} ) ;
ZODには、数握りの数字固有の検証が含まれています。
z . number ( ) . gt ( 5 ) ;
z . number ( ) . gte ( 5 ) ; // alias .min(5)
z . number ( ) . lt ( 5 ) ;
z . number ( ) . lte ( 5 ) ; // alias .max(5)
z . number ( ) . int ( ) ; // value must be an integer
z . number ( ) . positive ( ) ; // > 0
z . number ( ) . nonnegative ( ) ; // >= 0
z . number ( ) . negative ( ) ; // < 0
z . number ( ) . nonpositive ( ) ; // <= 0
z . number ( ) . multipleOf ( 5 ) ; // Evenly divisible by 5. Alias .step(5)
z . number ( ) . finite ( ) ; // value must be finite, not Infinity or -Infinity
z . number ( ) . safe ( ) ; // value must be between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER
オプションで、2番目の引数を渡してカスタムエラーメッセージを提供できます。
z . number ( ) . lte ( 5 , { message : "this?is?too?big" } ) ;
Zodには、Bigint固有の検証がいくつか含まれています。
z . bigint ( ) . gt ( 5n ) ;
z . bigint ( ) . gte ( 5n ) ; // alias `.min(5n)`
z . bigint ( ) . lt ( 5n ) ;
z . bigint ( ) . lte ( 5n ) ; // alias `.max(5n)`
z . bigint ( ) . positive ( ) ; // > 0n
z . bigint ( ) . nonnegative ( ) ; // >= 0n
z . bigint ( ) . negative ( ) ; // < 0n
z . bigint ( ) . nonpositive ( ) ; // <= 0n
z . bigint ( ) . multipleOf ( 5n ) ; // Evenly divisible by 5n.
NANスキーマを作成するときに、特定のエラーメッセージをカスタマイズできます。
const isNaN = z . nan ( {
required_error : "isNaN is required" ,
invalid_type_error : "isNaN must be 'not a number'" ,
} ) ;
ブールスキーマを作成するときに、特定のエラーメッセージをカスタマイズできます。
const isActive = z . boolean ( {
required_error : "isActive is required" ,
invalid_type_error : "isActive must be a boolean" ,
} ) ;
z.date()を使用して、 Date
インスタンスを検証します。
z . date ( ) . safeParse ( new Date ( ) ) ; // success: true
z . date ( ) . safeParse ( "2022-01-12T00:00:00.000Z" ) ; // success: false
日付スキーマを作成するときに、特定のエラーメッセージをカスタマイズできます。
const myDateSchema = z . date ( {
required_error : "Please select a date and time" ,
invalid_type_error : "That's not a date!" ,
} ) ;
Zodは、ほんの一握りの日付固有の検証を提供します。
z . date ( ) . min ( new Date ( "1900-01-01" ) , { message : "Too old" } ) ;
z . date ( ) . max ( new Date ( ) , { message : "Too young!" } ) ;
これまでの強制
ZOD 3.20以降、 z.coerce.date()
を使用して、 new Date(input)
に入力を渡します。
const dateSchema = z . coerce . date ( ) ;
type DateSchema = z . infer < typeof dateSchema > ;
// type DateSchema = Date
/* valid dates */
console . log ( dateSchema . safeParse ( "2023-01-10T00:00:00.000Z" ) . success ) ; // true
console . log ( dateSchema . safeParse ( "2023-01-10" ) . success ) ; // true
console . log ( dateSchema . safeParse ( "1/10/23" ) . success ) ; // true
console . log ( dateSchema . safeParse ( new Date ( "1/10/23" ) ) . success ) ; // true
/* invalid dates */
console . log ( dateSchema . safeParse ( "2023-13-10" ) . success ) ; // false
console . log ( dateSchema . safeParse ( "0000-00-00" ) . success ) ; // false
古いZODバージョンの場合、このスレッドに記載されているようなz.preprocess
を使用します。
const FishEnum = z . enum ( [ "Salmon" , "Tuna" , "Trout" ] ) ;
type FishEnum = z . infer < typeof FishEnum > ;
// 'Salmon' | 'Tuna' | 'Trout'
z.enum
許容文字列値の固定セットでスキーマを宣言するZOD-NATIVEの方法です。値の配列をz.enum()
に直接渡します。または、 as const
使用して、列挙値をひものタプルとして定義します。詳細については、const Assertion Docsを参照してください。
const VALUES = [ "Salmon" , "Tuna" , "Trout" ] as const ;
const FishEnum = z . enum ( VALUES ) ;
Zodは各要素の正確な値を推測できないため、これは許可されていません。
const fish = [ "Salmon" , "Tuna" , "Trout" ] ;
const FishEnum = z . enum ( fish ) ;
.enum
ZOD enumでオートコンプリートを取得するには、スキーマの.enum
プロパティを使用してください。
FishEnum . enum . Salmon ; // => autocompletes
FishEnum . enum ;
/*
=> {
Salmon: "Salmon",
Tuna: "Tuna",
Trout: "Trout",
}
*/
また、 .options
プロパティを備えたタプルとしてオプションのリストを取得することもできます。
FishEnum . options ; // ["Salmon", "Tuna", "Trout"];
.exclude/.extract()
.exclude
および.extract
メソッドを使用して、Zod enumのサブセットを作成できます。
const FishEnum = z . enum ( [ "Salmon" , "Tuna" , "Trout" ] ) ;
const SalmonAndTrout = FishEnum . extract ( [ "Salmon" , "Trout" ] ) ;
const TunaOnly = FishEnum . exclude ( [ "Salmon" , "Trout" ] ) ;
Zod enumsは、列挙を定義および検証するための推奨アプローチです。ただし、サードパーティライブラリからの列挙に対して検証する必要がある場合(または、既存の酵素を書き換えたくない場合) z.nativeEnum()
使用できます。
数字列挙
enum Fruits {
Apple ,
Banana ,
}
const FruitEnum = z . nativeEnum ( Fruits ) ;
type FruitEnum = z . infer < typeof FruitEnum > ; // Fruits
FruitEnum . parse ( Fruits . Apple ) ; // passes
FruitEnum . parse ( Fruits . Banana ) ; // passes
FruitEnum . parse ( 0 ) ; // passes
FruitEnum . parse ( 1 ) ; // passes
FruitEnum . parse ( 3 ) ; // fails
文字列列挙
enum Fruits {
Apple = "apple" ,
Banana = "banana" ,
Cantaloupe , // you can mix numerical and string enums
}
const FruitEnum = z . nativeEnum ( Fruits ) ;
type FruitEnum = z . infer < typeof FruitEnum > ; // Fruits
FruitEnum . parse ( Fruits . Apple ) ; // passes
FruitEnum . parse ( Fruits . Cantaloupe ) ; // passes
FruitEnum . parse ( "apple" ) ; // passes
FruitEnum . parse ( "banana" ) ; // passes
FruitEnum . parse ( 0 ) ; // passes
FruitEnum . parse ( "Cantaloupe" ) ; // fails
const enums
.nativeEnum()
関数は、 as const
も機能します。as const
!
const Fruits = {
Apple : "apple" ,
Banana : "banana" ,
Cantaloupe : 3 ,
} as const ;
const FruitEnum = z . nativeEnum ( Fruits ) ;
type FruitEnum = z . infer < typeof FruitEnum > ; // "apple" | "banana" | 3
FruitEnum . parse ( "apple" ) ; // passes
FruitEnum . parse ( "banana" ) ; // passes
FruitEnum . parse ( 3 ) ; // passes
FruitEnum . parse ( "Cantaloupe" ) ; // fails
.enum
プロパティを使用して、基礎となるオブジェクトにアクセスできます。
FruitEnum . enum . Apple ; // "apple"
z.optional()
を使用して、すべてのスキーマをオプションにすることができます。これにより、スキーマがZodOptional
インスタンスでラップされ、結果が返されます。
const schema = z . optional ( z . string ( ) ) ;
schema . parse ( undefined ) ; // => returns undefined
type A = z . infer < typeof schema > ; // string | undefined
便宜上、既存のスキーマの.optional()
メソッドを呼び出すこともできます。
const user = z . object ( {
username : z . string ( ) . optional ( ) ,
} ) ;
type C = z . infer < typeof user > ; // { username?: string | undefined };
.unwrap()
を使用して、 ZodOptional
インスタンスからラップされたスキーマを抽出できます。
const stringSchema = z . string ( ) ;
const optionalString = stringSchema . optional ( ) ;
optionalString . unwrap ( ) === stringSchema ; // true
同様に、 z.nullable()
でnullableタイプを作成できます。
const nullableString = z . nullable ( z . string ( ) ) ;
nullableString . parse ( "asdf" ) ; // => "asdf"
nullableString . parse ( null ) ; // => null
または.nullable()
メソッドを使用します。
const E = z . string ( ) . nullable ( ) ; // equivalent to nullableString
type E = z . infer < typeof E > ; // string | null
.unwrap()
で内部スキーマを抽出します。
const stringSchema = z . string ( ) ;
const nullableString = stringSchema . nullable ( ) ;
nullableString . unwrap ( ) === stringSchema ; // true
// all properties are required by default
const Dog = z . object ( {
name : z . string ( ) ,
age : z . number ( ) ,
} ) ;
// extract the inferred type like this
type Dog = z . infer < typeof Dog > ;
// equivalent to:
type Dog = {
name : string ;
age : number ;
} ;
.shape
.shape
使用して、特定のキーのスキーマにアクセスします。
Dog . shape . name ; // => string schema
Dog . shape . age ; // => number schema
.keyof
.keyof
使用して、オブジェクトスキーマのキーからZodEnum
を作成します。
const keySchema = Dog . keyof ( ) ;
keySchema ; // ZodEnum<["name", "age"]>
.extend
.extend
メソッドを使用して、オブジェクトスキーマに追加のフィールドを追加できます。
const DogWithBreed = Dog . extend ( {
breed : z . string ( ) ,
} ) ;
.extend
使用してフィールドを上書きします!この力に注意してください!
.merge
A.extend(B.shape)
に相当します。
const BaseTeacher = z . object ( { students : z . array ( z . string ( ) ) } ) ;
const HasID = z . object ( { id : z . string ( ) } ) ;
const Teacher = BaseTeacher . merge ( HasID ) ;
type Teacher = z . infer < typeof Teacher > ; // => { students: string[], id: string }
2つのスキーマがキーを共有する場合、BのプロパティがAのプロパティを上書きする場合、返されたスキーマは「未知のキー」ポリシー(ストリップ/厳格/パススルー)とBのキャッチオールスキーマも継承します。
.pick/.omit
タイプスクリプトのビルトインPick
およびOmit
ユーティリティタイプに触発されたすべてのZODオブジェクトスキーマには、変更されたバージョンを返す.pick
および.omit
メソッドがあります。このレシピスキーマを考えてみましょう。
const Recipe = z . object ( {
id : z . string ( ) ,
name : z . string ( ) ,
ingredients : z . array ( z . string ( ) ) ,
} ) ;
特定のキーのみを保持するには、 .pick
を使用してください。
const JustTheName = Recipe . pick ( { name : true } ) ;
type JustTheName = z . infer < typeof JustTheName > ;
// => { name: string }
特定のキーを削除するには、 .omit
を使用してください。
const NoIDRecipe = Recipe . omit ( { id : true } ) ;
type NoIDRecipe = z . infer < typeof NoIDRecipe > ;
// => { name: string, ingredients: string[] }
.partial
組み込み型タイプスクリプトユーティリティタイプの部分的にインスピレーションを得て、 .partial
Methodはすべてのプロパティをオプションにします。
このオブジェクトから始まります:
const user = z . object ( {
email : z . string ( ) ,
username : z . string ( ) ,
} ) ;
// { email: string; username: string }
部分バージョンを作成できます。
const partialUser = user . partial ( ) ;
// { email?: string | undefined; username?: string | undefined }
オプションを作成するプロパティを指定することもできます。
const optionalEmail = user . partial ( {
email : true ,
} ) ;
/*
{
email?: string | undefined;
username: string
}
*/
.deepPartial
.partial
Methodは浅いです - 深さは1つのレベルのみを適用します。 「ディープ」バージョンもあります。
const user = z . object ( {
username : z . string ( ) ,
location : z . object ( {
latitude : z . number ( ) ,
longitude : z . number ( ) ,
} ) ,
strings : z . array ( z . object ( { value : z . string ( ) } ) ) ,
} ) ;
const deepPartialUser = user . deepPartial ( ) ;
/*
{
username?: string | undefined,
location?: {
latitude?: number | undefined;
longitude?: number | undefined;
} | undefined,
strings?: { value?: string}[]
}
*/
重要な制限:深い部分的な部分は、オブジェクト、配列、およびタプルの階層で予想どおりに機能します。
.required
.partial
メソッドとは反対に、 .required
メソッドはすべてのプロパティを必要とします。
このオブジェクトから始まります:
const user = z
. object ( {
email : z . string ( ) ,
username : z . string ( ) ,
} )
. partial ( ) ;
// { email?: string | undefined; username?: string | undefined }
必要なバージョンを作成できます。
const requiredUser = user . required ( ) ;
// { email: string; username: string }
また、必要なプロパティを指定することもできます。
const requiredEmail = user . required ( {
email : true ,
} ) ;
/*
{
email: string;
username?: string | undefined;
}
*/
.passthrough
デフォルトでは、ZODオブジェクトスキーマ解析中に認識されていないキーをストリップします。
const person = z . object ( {
name : z . string ( ) ,
} ) ;
person . parse ( {
name : "bob dylan" ,
extraKey : 61 ,
} ) ;
// => { name: "bob dylan" }
// extraKey has been stripped
代わりに、不明なキーを通過する場合は、 .passthrough()
を使用します。
person . passthrough ( ) . parse ( {
name : "bob dylan" ,
extraKey : 61 ,
} ) ;
// => { name: "bob dylan", extraKey: 61 }
.strict
デフォルトでは、ZODオブジェクトスキーマ解析中に認識されていないキーをストリップします。 .strict()
を使用して不明なキーを禁止できます。入力に不明なキーがある場合、ZODはエラーをスローします。
const person = z
. object ( {
name : z . string ( ) ,
} )
. strict ( ) ;
person . parse ( {
name : "bob dylan" ,
extraKey : 61 ,
} ) ;
// => throws ZodError
.strip
.strip
メソッドを使用して、オブジェクトスキーマをデフォルトの動作(認識されていないキーを削除)にリセットできます。
.catchall
「キャッチオール」スキーマをオブジェクトスキーマに渡すことができます。すべての未知のキーはそれに対して検証されます。
const person = z
. object ( {
name : z . string ( ) ,
} )
. catchall ( z . number ( ) ) ;
person . parse ( {
name : "bob dylan" ,
validExtraKey : 61 , // works fine
} ) ;
person . parse ( {
name : "bob dylan" ,
validExtraKey : false , // fails
} ) ;
// => throws ZodError
.catchall()
を使用して、 .passthrough()
.strip()
、または.strict()
をoveriatesします。現在、すべてのキーが「既知」と見なされています。
const stringArray = z . array ( z . string ( ) ) ;
// equivalent
const stringArray = z . string ( ) . array ( ) ;
.array()
メソッドには注意してください。新しいZodArray
インスタンスを返します。これは、メソッドと呼ばれる順序が重要であることを意味します。例えば:
z . string ( ) . optional ( ) . array ( ) ; // (string | undefined)[]
z . string ( ) . array ( ) . optional ( ) ; // string[] | undefined
.element
.element
使用して、配列の要素のスキーマにアクセスします。
stringArray . element ; // => string schema
.nonempty
配列に少なくとも1つの要素が含まれていることを確認する場合は、 .nonempty()
を使用します。
const nonEmptyStrings = z . string ( ) . array ( ) . nonempty ( ) ;
// the inferred type is now
// [string, ...string[]]
nonEmptyStrings . parse ( [ ] ) ; // throws: "Array cannot be empty"
nonEmptyStrings . parse ( [ "Ariana Grande" ] ) ; // passes
オプションでカスタムエラーメッセージを指定できます。
// optional custom error message
const nonEmptyStrings = z . string ( ) . array ( ) . nonempty ( {
message : "Can't be empty!" ,
} ) ;
.min/.max/.length
z . string ( ) . array ( ) . min ( 5 ) ; // must contain 5 or more items
z . string ( ) . array ( ) . max ( 5 ) ; // must contain 5 or fewer items
z . string ( ) . array ( ) . length ( 5 ) ; // must contain 5 items exactly
.nonempty()
とは異なり、これらのメソッドは推測されたタイプを変更しません。
アレイとは異なり、タプルには固定数の要素があり、各要素は異なるタイプを持つことができます。
const athleteSchema = z . tuple ( [
z . string ( ) , // name
z . number ( ) , // jersey number
z . object ( {
pointsScored : z . number ( ) ,
} ) , // statistics
] ) ;
type Athlete = z . infer < typeof athleteSchema > ;
// type Athlete = [string, number, { pointsScored: number }]
.rest
メソッドを使用して、variadic( "rest")引数を追加できます。
const variadicTuple = z . tuple ( [ z . string ( ) ] ) . rest ( z . number ( ) ) ;
const result = variadicTuple . parse ( [ "hello" , 1 , 2 , 3 ] ) ;
// => [string, ...number[]];
ZODには、作曲のための組み込みz.union
メソッドが含まれています。
const stringOrNumber = z . union ( [ z . string ( ) , z . number ( ) ] ) ;
stringOrNumber . parse ( "foo" ) ; // passes
stringOrNumber . parse ( 14 ) ; // passes
Zodは、「オプション」のそれぞれに対する入力を順番にテストし、正常に検証する最初の値を返します。
便宜上、 .or
メソッドを使用することもできます。
const stringOrNumber = z . string ( ) . or ( z . number ( ) ) ;
オプションの文字列検証:
オプションのフォーム入力を検証するには、空の文字列リテラルと目的の文字列検証を結合できます。
この例では、オプションであるが有効なURLを含める必要がある入力を検証します。
const optionalUrl = z . union ( [ z . string ( ) . url ( ) . nullish ( ) , z . literal ( "" ) ] ) ;
console . log ( optionalUrl . safeParse ( undefined ) . success ) ; // true
console . log ( optionalUrl . safeParse ( null ) . success ) ; // true
console . log ( optionalUrl . safeParse ( "" ) . success ) ; // true
console . log ( optionalUrl . safeParse ( "https://zod.dev" ) . success ) ; // true
console . log ( optionalUrl . safeParse ( "not a valid url" ) . success ) ; // false
差別された組合は、すべてが特定の鍵を共有するオブジェクトスキーマの連合です。
type MyUnion =
| { status : "success" ; data : string }
| { status : "failed" ; error : Error } ;
このような組合は、 z.discriminatedUnion
メソッドで表現できます。これにより、ZODは識別子キー(上記の例のstatus
)をチェックして、入力を解析するためにどのスキーマを使用するかを決定できるため、より速い評価が可能になります。これにより、解析がより効率的になり、Zodがより友好的なエラーを報告できます。
基本的な組合方式では、入力は提供された各「オプション」に対してテストされ、無効性の場合、すべての「オプション」の問題がZODエラーに表示されます。一方、差別された組合は、「オプション」の1つだけを選択し、それに対してテストし、この「オプション」に関連する問題のみを示すことを許可しています。
const myUnion = z . discriminatedUnion ( "status" , [
z . object ( { status : z . literal ( "success" ) , data : z . string ( ) } ) ,
z . object ( { status : z . literal ( "failed" ) , error : z . instanceof ( Error ) } ) ,
] ) ;
myUnion . parse ( { status : "success" , data : "yippie ki yay" } ) ;
.options
プロパティを使用して、スキーマの配列への参照を抽出できます。
myUnion . options ; // [ZodObject<...>, ZodObject<...>]
2つ以上の差別された組合を統合するには、 .options
を破壊します。
const A = z . discriminatedUnion ( "status" , [
/* options */
] ) ;
const B = z . discriminatedUnion ( "status" , [
/* options */
] ) ;
const AB = z . discriminatedUnion ( "status" , [ ... A . options , ... B . options ] ) ;
レコードスキーマはRecord<string, number>
などのタイプを検証するために使用されます。これは、IDによるアイテムの保存またはキャッシュに特に役立ちます。
const User = z . object ( { name : z . string ( ) } ) ;
const UserStore = z . record ( z . string ( ) , User ) ;
type UserStore = z . infer < typeof UserStore > ;
// => Record<string, { name: string }>
スキーマと推測されたタイプは、次のように使用できます。
const userStore : UserStore = { } ;
userStore [ "77d2586b-9e8e-4ecf-8b21-ea7e0530eadd" ] = {
name : "Carlotta" ,
} ; // passes
userStore [ "77d2586b-9e8e-4ecf-8b21-ea7e0530eadd" ] = {
whatever : "Ice cream sundae" ,
} ; // TypeError
数値キーに関するメモ
z.record(keyType, valueType)
数値キータイプとTypeScriptの組み込みレコードタイプRecord<KeyType, ValueType>
ことができますが、ZODのTypeScript Type Record<number, any>
を表すのは困難です。
結局のところ、 [k: number]
を取り巻くタイプスクリプトの動作は少し直感的ではありません:
const testMap : { [ k : number ] : string } = {
1 : "one" ,
} ;
for ( const key in testMap ) {
console . log ( ` ${ key } : ${ typeof key } ` ) ;
}
// prints: `1: string`
ご覧のとおり、JavaScriptはすべてのオブジェクトキーをフードの下に文字列に自動的にキャストします。 Zodは静的タイプとランタイムタイプの間のギャップを埋めようとしているため、ランタイムJavaScriptには数値キーのようなものがないため、数値キーでレコードスキーマを作成する方法を提供することは意味がありません。
const stringNumberMap = z . map ( z . string ( ) , z . number ( ) ) ;
type StringNumberMap = z . infer < typeof stringNumberMap > ;
// type StringNumberMap = Map<string, number>
const numberSet = z . set ( z . number ( ) ) ;
type NumberSet = z . infer < typeof numberSet > ;
// type NumberSet = Set<number>
セットスキーマは、次のユーティリティ方法でさらに制約できます。
z . set ( z . string ( ) ) . nonempty ( ) ; // must contain at least one item
z . set ( z . string ( ) ) . min ( 5 ) ; // must contain 5 or more items
z . set ( z . string ( ) ) . max ( 5 ) ; // must contain 5 or fewer items
z . set ( z . string ( ) ) . size ( 5 ) ; // must contain 5 items exactly
交差点は、「論理的および」タイプを作成するのに役立ちます。これは、2つのオブジェクトタイプと交差するのに役立ちます。
const Person = z . object ( {
name : z . string ( ) ,
} ) ;
const Employee = z . object ( {
role : z . string ( ) ,
} ) ;
const EmployedPerson = z . intersection ( Person , Employee ) ;
// equivalent to:
const EmployedPerson = Person . and ( Employee ) ;
多くの場合、 A.merge(B)
使用して2つのオブジェクトをマージすることをお勧めします。 .merge
メソッドは新しいZodObject
インスタンスを返しますが、 A.and(B)
pick
やomit
などの一般的なオブジェクトメソッドを欠いているあまり有用でないZodIntersection
インスタンスを返します。
const a = z . union ( [ z . number ( ) , z . string ( ) ] ) ;
const b = z . union ( [ z . number ( ) , z . boolean ( ) ] ) ;
const c = z . intersection ( a , b ) ;
type c = z . infer < typeof c > ; // => number
ZODの再帰スキーマを定義できますが、TypeScriptの制限のため、それらのタイプは静的に推測することはできません。代わりに、タイプ定義を手動で定義し、「タイプのヒント」としてZODに提供する必要があります。
const baseCategorySchema = z . object ( {
name : z . string ( ) ,
} ) ;
type Category = z . infer < typeof baseCategorySchema > & {
subcategories : Category [ ] ;
} ;
const categorySchema : z . ZodType < Category > = baseCategorySchema . extend ( {
subcategories : z . lazy ( ( ) => categorySchema . array ( ) ) ,
} ) ;
categorySchema . parse ( {
name : "People" ,
subcategories : [
{
name : "Politicians" ,
subcategories : [
{
name : "Presidents" ,
subcategories : [ ] ,
} ,
] ,
} ,
] ,
} ) ; // passes
この例についてはCrasiteに感謝します。
z.ZodEffects
( .refine
、 .transform
、 preprocess
など)を使用してz.ZodType
を使用する場合、スキーマの入力と出力タイプを定義する必要があります。 z.ZodType<Output, z.ZodTypeDef, Input>
const isValidId = ( id : string ) : id is `${ string } /${ string } ` =>
id . split ( "/" ) . length === 2 ;
const baseSchema = z . object ( {
id : z . string ( ) . refine ( isValidId ) ,
} ) ;
type Input = z . input < typeof baseSchema > & {
children : Input [ ] ;
} ;
type Output = z . output < typeof baseSchema > & {
children : Output [ ] ;
} ;
const schema : z . ZodType < Output , z . ZodTypeDef , Input > = baseSchema . extend ( {
children : z . lazy ( ( ) => schema . array ( ) ) ,
} ) ;
この例については、Marcus13371337とJoelbeeldiに感謝します。
JSON値を検証する場合は、以下のスニペットを使用できます。
const literalSchema = z . union ( [ z . string ( ) , z . number ( ) , z . boolean ( ) , z . null ( ) ] ) ;
type Literal = z . infer < typeof literalSchema > ;
type Json = Literal | { [ key : string ] : Json } | Json [ ] ;
const jsonSchema : z . ZodType < Json > = z . lazy ( ( ) =>
z . union ( [ literalSchema , z . array ( jsonSchema ) , z . record ( jsonSchema ) ] )
) ;
jsonSchema . parse ( data ) ;
これを提案してくれたGgoodmanに感謝します。
再帰スキーマをサポートしているにもかかわらず、循環データをZODに渡すと、場合によっては無限のループが発生します。
周期的なオブジェクトが問題を引き起こす前に検出するには、このアプローチを検討してください。
const numberPromise = z . promise ( z . number ( ) ) ;
「解析」は、約束のスキーマで少し異なって機能します。検証は2つの部分で行われます。
.then
および.catch
メソッドを持つオブジェクト。)。.then
既存の約束に追加の検証ステップを添付するために使用します。検証障害を処理するために、返された約束で.catch
使用する必要があります。 numberPromise . parse ( "tuna" ) ;
// ZodError: Non-Promise type: string
numberPromise . parse ( Promise . resolve ( "tuna" ) ) ;
// => Promise<number>
const test = async ( ) => {
await numberPromise . parse ( Promise . resolve ( "tuna" ) ) ;
// ZodError: Non-number type: string
await numberPromise . parse ( Promise . resolve ( 3.14 ) ) ;
// => 3.14
} ;
z.instanceof
使用して、入力がクラスのインスタンスであることを確認できます。これは、サードパーティライブラリからエクスポートされるクラスに対する入力を検証するのに役立ちます。
class Test {
name : string ;
}
const TestSchema = z . instanceof ( Test ) ;
const blob : any = "whatever" ;
TestSchema . parse ( new Test ( ) ) ; // passes
TestSchema . parse ( blob ) ; // throws
Zodでは、「関数スキーマ」を定義することもできます。これにより、検証コードと「ビジネスロジック」を混合することなく、関数の入力と出力を簡単に検証できます。
z.function(args, returnType)
を備えた関数スキーマを作成できます。
const myFunction = z . function ( ) ;
type myFunction = z . infer < typeof myFunction > ;
// => ()=>unknown
入力と出力を定義します。
const myFunction = z
. function ( )
. args ( z . string ( ) , z . number ( ) ) // accepts an arbitrary number of arguments
. returns ( z . boolean ( ) ) ;
type myFunction = z . infer < typeof myFunction > ;
// => (arg0: string, arg1: number)=>boolean
関数スキーマには、関数を受け入れ、入力と出力を自動的に検証する新しい関数を返す.implement()
メソッドがあります。
const trimmedLength = z
. function ( )
. args ( z . string ( ) ) // accepts an arbitrary number of arguments
. returns ( z . number ( ) )
. implement ( ( x ) => {
// TypeScript knows x is a string!
return x . trim ( ) . length ;
} ) ;
trimmedLength ( "sandwich" ) ; // => 8
trimmedLength ( " asdf " ) ; // => 4
入力の検証のみを気にする場合は、 .returns()
メソッドを呼び出しないでください。出力タイプは、実装から推測されます。
関数が何も返さない場合は、特別な
z.void()
オプションを使用できます。これにより、ZODはボイド戻り機能のタイプを適切に推測できます。 (void-returning関数は実際には未定義です。)
const myFunction = z
. function ( )
. args ( z . string ( ) )
. implement ( ( arg ) => {
return [ arg . length ] ;
} ) ;
myFunction ; // (arg: string)=>number[]
関数スキーマから入力スキーマと出力スキーマを抽出します。
myFunction . parameters ( ) ;
// => ZodTuple<[ZodString, ZodNumber]>
myFunction . returnType ( ) ;
// => ZodBoolean
Zodは、
.preprocess()
を必要とせずに原始的な強制をサポートしています。詳細については、強制ドキュメントを参照してください。
通常、ZODは「解析」パラダイムの下で動作します。 Zodは最初に入力を検証し、次に変換関数のチェーンに渡します。 (変換の詳細については、.transformドキュメントをお読みください。)
ただし、ペーシングが発生する前に、入力に変換を適用したい場合があります。一般的なユースケース:強制タイプ。 zodはz.preprocess()
でこれを有効にします。
const castToString = z . preprocess ( ( val ) => String ( val ) , z . string ( ) ) ;
これにより、 ZodEffects
インスタンスが返されます。 ZodEffects
前処理、改良、および変換に関するすべてのロジックを含むラッパークラスです。
z.custom()
を使用して、任意のTypeScriptタイプのZODスキーマを作成できます。これは、テンプレート文字列リテラルなど、Zodからサポートされていないタイプのスキーマを作成するのに役立ちます。
const px = z . custom < `${ number } px` > ( ( val ) => {
return typeof val === "string" ? / ^d+px$ / . test ( val ) : false ;
} ) ;
type px = z . infer < typeof px > ; // `${number}px`
px . parse ( "42px" ) ; // "42px"
px . parse ( "42vw" ) ; // throws;
検証関数を提供しない場合、ZODは任意の価値を許可します。これは危険です!
z . custom < { arg : string } > ( ) ; // performs no validation
2番目の引数を渡すことにより、エラーメッセージやその他のオプションをカスタマイズできます。このパラメーターは、 .refine
のparamsパラメーターと同じように機能します。
z . custom < ... > ( ( val ) => ... , "custom error message" ) ;
すべてのZODスキーマには、特定の方法が含まれています。
.parse
.parse(data: unknown): T
ZODスキーマを考えると、 data
確認するために.parse
メソッドを呼び出すことが有効です。もしそうなら、完全なタイプ情報で値が返されます!それ以外の場合、エラーがスローされます。
重要:
.parse
によって返される値は、渡された変数の深いクローンです。
const stringSchema = z . string ( ) ;
stringSchema . parse ( "fish" ) ; // => returns "fish"
stringSchema . parse ( 12 ) ; // throws error
.parseAsync
.parseAsync(data:unknown): Promise<T>
非同期の改良または変換を使用する場合(後で詳しく説明します)、. .parseAsync
を使用する必要があります。
const stringSchema = z . string ( ) . refine ( async ( val ) => val . length <= 8 ) ;
await stringSchema . parseAsync ( "hello" ) ; // => returns "hello"
await stringSchema . parseAsync ( "hello world" ) ; // => throws error
.safeParse
.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }
検証が失敗したときにzodをスローする必要がない場合は、 .safeParse
使用してください。このメソッドは、検証問題に関する詳細な情報を含む、正常に解析されたデータまたはZoderrorインスタンスを含むオブジェクトを返します。
stringSchema . safeParse ( 12 ) ;
// => { success: false; error: ZodError }
stringSchema . safeParse ( "billie" ) ;
// => { success: true; data: 'billie' }
結果は差別された組合であるため、エラーを非常に便利に処理できます。
const result = stringSchema . safeParse ( "billie" ) ;
if ( ! result . success ) {
// handle error then return
result . error ;
} else {
// do something
result . data ;
}
.safeParseAsync
エイリアス:
.spa
safeParse
の非同期バージョン。
await stringSchema . safeParseAsync ( "billie" ) ;
For convenience, this has been aliased to .spa
:
await stringSchema . spa ( "billie" ) ;
.refine
.refine(validator: (data:T)=>any, params?: RefineParams)
ZODでは、改良を介してカスタム検証ロジックを提供できます。 (複数の問題の作成やエラーコードのカスタマイズなどの高度な機能については、 .superRefine
を参照してください。)
ZODは、タイプスクリプトを可能な限り密接に反映するように設計されています。しかし、TypeScriptのタイプシステムでは表現できないことを確認したいといういわゆる「洗練タイプ」がたくさんあります。たとえば、数字が整数であること、または文字列が有効な電子メールアドレスであることを確認します。
たとえば、 .refine
を使用してzodスキーマのカスタム検証チェックを定義できます。
const myString = z . string ( ) . refine ( ( val ) => val . length <= 255 , {
message : "String can't be more than 255 characters" ,
} ) ;
ショ和 洗練された関数は投げるべきではありません。代わりに、故障を信号するためにfalsy値を返す必要があります。
ご覧のとおり、 .refine
2つの議論を取ります。
T
- スキーマの推定タイプ)を取得し、 any
を返します。真実の値は検証に合格します。 ([email protected]の前に、検証関数はブール値を返す必要がありました。) type RefineParams = {
// override error message
message ?: string ;
// appended to error path
path ?: ( string | number ) [ ] ;
// params object you can use to customize message
// in error map
params ?: object ;
} ;
高度なケースの場合、2番目の引数は、 RefineParams
返す関数でもあります。
const longString = z . string ( ) . refine (
( val ) => val . length > 10 ,
( val ) => ( { message : ` ${ val } is not more than 10 characters` } )
) ;
const passwordForm = z
. object ( {
password : z . string ( ) ,
confirm : z . string ( ) ,
} )
. refine ( ( data ) => data . password === data . confirm , {
message : "Passwords don't match" ,
path : [ "confirm" ] , // path of error
} ) ;
passwordForm . parse ( { password : "asdf" , confirm : "qwer" } ) ;
path
パラメーターを提供したため、結果のエラーは次のとおりです。
ZodError {
issues : [ {
"code" : "custom" ,
"path" : [ "confirm" ] ,
"message" : "Passwords don't match"
} ]
}
改良性も非同期にすることができます。
const userId = z . string ( ) . refine ( async ( id ) => {
// verify that ID exists in database
return true ;
} ) ;
ショ和 Asyncの改良を使用する場合は、.parseAsync
メソッドを使用してデータを解析する必要があります。それ以外の場合、Zodはエラーを投げます。
変換と改良はインターリーブすることができます:
z . string ( )
. transform ( ( val ) => val . length )
. refine ( ( val ) => val > 25 ) ;
.superRefine
.refine
メソッドは、実際にはsuperRefine
と呼ばれるより汎用性の高い(および冗長な)メソッドの上にある構文糖です。これが例です:
const Strings = z . array ( z . string ( ) ) . superRefine ( ( val , ctx ) => {
if ( val . length > 3 ) {
ctx . addIssue ( {
code : z . ZodIssueCode . too_big ,
maximum : 3 ,
type : "array" ,
inclusive : true ,
message : "Too many items ?" ,
} ) ;
}
if ( val . length !== new Set ( val ) . size ) {
ctx . addIssue ( {
code : z . ZodIssueCode . custom ,
message : `No duplicates allowed.` ,
} ) ;
}
} ) ;
好きなだけ多くの問題を追加できます。関数の実行中にctx.addIssue
が呼び出されない場合、検証が通過します。
通常、改良は常にZodIssueCode.custom
エラーコードで問題を作成しますが、 superRefine
ではZodIssueCode
の問題を投げることができます。各問題コードについては、エラー処理ガイド:error_handling.mdで詳細に説明されています。
デフォルトでは、洗練されたチェックが失敗した後でも解析は継続されます。たとえば、複数の精製を統合すると、すべてが実行されます。ただし、その後の改良が実行されないようにするために、早期に中止することが望ましい場合があります。これを達成するには、 fatal
旗をctx.addIssue
に渡し、 z.NEVER
を返します。
const schema = z . number ( ) . superRefine ( ( val , ctx ) => {
if ( val < 10 ) {
ctx . addIssue ( {
code : z . ZodIssueCode . custom ,
message : "should be >= 10" ,
fatal : true ,
} ) ;
return z . NEVER ;
}
if ( val !== 12 ) {
ctx . addIssue ( {
code : z . ZodIssueCode . custom ,
message : "should be twelve" ,
} ) ;
}
} ) ;
.refine()
または.superRefine()
に型述語を提供すると、結果のタイプはプレンシティのタイプに絞り込まれます。これは、複数の鎖の改良と変換を混合している場合に役立ちます。
const schema = z
. object ( {
first : z . string ( ) ,
second : z . number ( ) ,
} )
. nullable ( )
. superRefine ( ( arg , ctx ) : arg is { first : string ; second : number } => {
if ( ! arg ) {
ctx . addIssue ( {
code : z . ZodIssueCode . custom , // customize your issue
message : "object should exist" ,
} ) ;
}
return z . NEVER ; // The return value is not used, but we need to return something to satisfy the typing
} )
// here, TS knows that arg is not null
. refine ( ( arg ) => arg . first === "bob" , "`first` is not `bob`!" ) ;
ショ和 ブール値を返す代わりに、ctx.addIssue()
を使用して、検証が合格するかどうかを示す必要があります。関数の実行中にctx.addIssue
が呼び出されない場合、検証が通過します。
.transform
解析後にデータを変換するには、 transform
方法を使用します。
const stringToNumber = z . string ( ) . transform ( ( val ) => val . length ) ;
stringToNumber . parse ( "string" ) ; // => 6
Note that stringToNumber
above is an instance of the ZodEffects
subclass. ZodString
のインスタンスではありません。 ZodString
の組み込みメソッド(Eg .email()
)を使用する場合は、変換前にそれらの方法を適用する必要があります。
const emailToDomain = z
. string ( )
. email ( )
. transform ( ( val ) => val . split ( "@" ) [ 1 ] ) ;
emailToDomain . parse ( "[email protected]" ) ; // => example.com
.transform
メソッドは、値を同時に検証および変換できます。これは、多くの場合、 transform
とrefine
チェーンするよりもシンプルで重複していません。
.superRefine
と同様に、変換関数は、検証の問題を登録するために使用できる、 addIssue
法を備えたctx
オブジェクトを受信します。
const numberInString = z . string ( ) . transform ( ( val , ctx ) => {
const parsed = parseInt ( val ) ;
if ( isNaN ( parsed ) ) {
ctx . addIssue ( {
code : z . ZodIssueCode . custom ,
message : "Not a number" ,
} ) ;
// This is a special symbol you can use to
// return early from the transform function.
// It has type `never` so it does not affect the
// inferred return type.
return z . NEVER ;
}
return parsed ;
} ) ;
変換と改良はインターリーブできます。これらは、宣言された順序で実行されます。
const nameToGreeting = z
. string ( )
. transform ( ( val ) => val . toUpperCase ( ) )
. refine ( ( val ) => val . length > 15 )
. transform ( ( val ) => `Hello ${ val } ` )
. refine ( ( val ) => val . indexOf ( "!" ) === - 1 ) ;
変換は非同期でもあります。
const IdToUser = z
. string ( )
. uuid ( )
. transform ( async ( id ) => {
return await getUserById ( id ) ;
} ) ;
ショ和 スキーマに非同期変換が含まれている場合、データを解析するには.parseasync()または.safeparseasync()を使用する必要があります。それ以外の場合、Zodはエラーを投げます。
.default
変換を使用して、ZODで「デフォルト値」の概念を実装できます。
const stringWithDefault = z . string ( ) . default ( "tuna" ) ;
stringWithDefault . parse ( undefined ) ; // => "tuna"
オプションで、機能を.default
に渡すことができます。これは、デフォルト値を生成する必要がある場合に再実行される場合があります。
const numberWithRandomDefault = z . number ( ) . default ( Math . random ) ;
numberWithRandomDefault . parse ( undefined ) ; // => 0.4413456736055323
numberWithRandomDefault . parse ( undefined ) ; // => 0.1871840107401901
numberWithRandomDefault . parse ( undefined ) ; // => 0.7223408162401552
概念的には、これがZODがデフォルト値を処理する方法です。
undefined
の場合、デフォルト値が返されます.describe
.describe()
を使用して、結果のスキーマにdescription
プロパティを追加します。
const documentedString = z
. string ( )
. describe ( "A useful bit of text, if you know what to do with it." ) ;
documentedString . description ; // A useful bit of text…
これは、たとえばzod-to-json-schema
などのライブラリを使用したJSONスキーマなど、フィールドの文書化に役立ちます)。
.catch
Use .catch()
to provide a "catch value" to be returned in the event of a parsing error.
const numberWithCatch = z . number ( ) . catch ( 42 ) ;
numberWithCatch . parse ( 5 ) ; // => 5
numberWithCatch . parse ( "tuna" ) ; // => 42
オプションで、関数を.catch
に渡すことができます。これは、デフォルト値を生成する必要がある場合に再実行される場合があります。キャッチエラーを含むctx
オブジェクトは、この関数に渡されます。
const numberWithRandomCatch = z . number ( ) . catch ( ( ctx ) => {
ctx . error ; // the caught ZodError
return Math . random ( ) ;
} ) ;
numberWithRandomCatch . parse ( "sup" ) ; // => 0.4413456736055323
numberWithRandomCatch . parse ( "sup" ) ; // => 0.1871840107401901
numberWithRandomCatch . parse ( "sup" ) ; // => 0.7223408162401552
概念的には、これがZODが「キャッチ値」を処理する方法です。
.optional
スキーマのオプションバージョンを返す便利な方法。
const optionalString = z . string ( ) . optional ( ) ; // string | undefined
// equivalent to
z . optional ( z . string ( ) ) ;
.nullable
スキーマの無効なバージョンを返す便利な方法。
const nullableString = z . string ( ) . nullable ( ) ; // string | null
// equivalent to
z . nullable ( z . string ( ) ) ;
.nullish
スキーマの「Nullish」バージョンを返す便利な方法。 Nullishスキーマはundefined
とnull
両方を受け入れます。 TypeScript 3.7リリースノートの「Nullish」の概念の詳細については、詳細をご覧ください。
const nullishString = z . string ( ) . nullish ( ) ; // string | null | undefined
// equivalent to
z . string ( ) . nullable ( ) . optional ( ) ;
.array
指定されたタイプの配列スキーマを返す便利な方法:
const stringArray = z . string ( ) . array ( ) ; // string[]
// equivalent to
z . array ( z . string ( ) ) ;
.promise
約束タイプの利便性方法:
const stringPromise = z . string ( ) . promise ( ) ; // Promise<string>
// equivalent to
z . promise ( z . string ( ) ) ;
.or
組合タイプの便利な方法。
const stringOrNumber = z . string ( ) . or ( z . number ( ) ) ; // string | number
// equivalent to
z . union ( [ z . string ( ) , z . number ( ) ] ) ;
.and
交差点タイプを作成するための便利な方法。
const nameAndAge = z
. object ( { name : z . string ( ) } )
. and ( z . object ( { age : z . number ( ) } ) ) ; // { name: string } & { age: number }
// equivalent to
z . intersection ( z . object ( { name : z . string ( ) } ) , z . object ( { age : z . number ( ) } ) ) ;
.brand
.brand<T>() => ZodBranded<this, B>
TypeScriptのタイプシステムは構造的です。つまり、構造的に同等の2つのタイプが同じと見なされます。
type Cat = { name : string } ;
type Dog = { name : string } ;
const petCat = ( cat : Cat ) => { } ;
const fido : Dog = { name : "fido" } ;
petCat ( fido ) ; // works fine
場合によっては、タイプスクリプト内の公称タイピングをシミュレートすることが望ましい場合があります。たとえば、ZODによって検証された入力のみを受け入れる関数を書きたい場合があります。これは、ブランドタイプ(別名不透明タイプ)で実現できます。
const Cat = z . object ( { name : z . string ( ) } ) . brand < "Cat" > ( ) ;
type Cat = z . infer < typeof Cat > ;
const petCat = ( cat : Cat ) => { } ;
// this works
const simba = Cat . parse ( { name : "simba" } ) ;
petCat ( simba ) ;
// this doesn't
petCat ( { name : "fido" } ) ;
ボンネットの下では、これは交差点タイプを使用して「ブランド」を推測されたタイプに添付することで機能します。このようにして、プレーン/ブランドのデータ構造は、スキーマの推定タイプに割り当てられなくなりました。
const Cat = z . object ( { name : z . string ( ) } ) . brand < "Cat" > ( ) ;
type Cat = z . infer < typeof Cat > ;
// {name: string} & {[symbol]: "Cat"}
ブランドタイプは、 .parse
のランタイム結果に影響しないことに注意してください。静的なみの構成要素です。
.readonly
.readonly() => ZodReadonly<this>
このメソッドは、ベーススキーマを使用して入力を解析するZodReadonly
スキーマインスタンスを返し、結果にObject.freeze()
を呼び出します。推測されたタイプは、 readonly
としてマークされています。
const schema = z . object ( { name : z . string ( ) } ) . readonly ( ) ;
type schema = z . infer < typeof schema > ;
// Readonly<{name: string}>
const result = schema . parse ( { name : "fido" } ) ;
result . name = "simba" ; // error
推測されたタイプは、関連する場合、TypeScriptの組み込みの読み取りタイプを使用します。
z . array ( z . string ( ) ) . readonly ( ) ;
// readonly string[]
z . tuple ( [ z . string ( ) , z . number ( ) ] ) . readonly ( ) ;
// readonly [string, number]
z . map ( z . string ( ) , z . date ( ) ) . readonly ( ) ;
// ReadonlyMap<string, Date>
z . set ( z . string ( ) ) . readonly ( ) ;
// ReadonlySet<string>
.pipe
スキーマは、検証「パイプライン」にチェーンできます。 .transform()
後に結果を簡単に検証するのに役立ちます。
z . string ( )
. transform ( ( val ) => val . length )
. pipe ( z . number ( ) . min ( 5 ) ) ;
.pipe()
メソッドは、 ZodPipeline
インスタンスを返します。
.pipe()
使用して、 z.coerce
の一般的な問題を修正できます。選択した強制でうまく機能するタイプへの入力を制約できます。次に、 .pipe()
使用して、強制を適用します。
制約された入力なし:
const toDate = z . coerce . date ( ) ;
// works intuitively
console . log ( toDate . safeParse ( "2023-01-01" ) . success ) ; // true
// might not be what you want
console . log ( toDate . safeParse ( null ) . success ) ; // true
制約された入力付き:
const datelike = z . union ( [ z . number ( ) , z . string ( ) , z . date ( ) ] ) ;
const datelikeToDate = datelike . pipe ( z . coerce . date ( ) ) ;
// still works intuitively
console . log ( datelikeToDate . safeParse ( "2023-01-01" ) . success ) ; // true
// more likely what you want
console . log ( datelikeToDate . safeParse ( null ) . success ) ; // false
また、この手法を使用して、猛攻撃のエラーを投げる強制を避けることもできます。
制約された入力なし:
const toBigInt = z . coerce . bigint ( ) ;
// works intuitively
console . log ( toBigInt . safeParse ( "42" ) ) ; // true
// probably not what you want
console . log ( toBigInt . safeParse ( null ) ) ; // throws uncaught error
制約された入力付き:
const toNumber = z . number ( ) . or ( z . string ( ) ) . pipe ( z . coerce . number ( ) ) ;
const toBigInt = z . bigint ( ) . or ( toNumber ) . pipe ( z . coerce . bigint ( ) ) ;
// still works intuitively
console . log ( toBigInt . safeParse ( "42" ) . success ) ; // true
// error handled by zod, more likely what you want
console . log ( toBigInt . safeParse ( null ) . success ) ; // false
z.infer<typeof mySchema>
を使用して、スキーマのタイプスクリプトタイプを抽出できます。
const A = z . string ( ) ;
type A = z . infer < typeof A > ; // string
const u : A = 12 ; // TypeError
const u : A = "asdf" ; // compiles
変身はどうですか?
現実には、各ZODスキーマは、入力と出力の2つのタイプを内部的に追跡します。ほとんどのスキーマ( z.string()
など)では、これら2つは同じです。しかし、変換をミックスに追加すると、これらの2つの値が分岐する可能性があります。たとえばz.string().transform(val => val.length)
のstring
とnumber
の出力があります。
次のような入力タイプと出力タイプを個別に抽出できます。
const stringToNumber = z . string ( ) . transform ( ( val ) => val . length ) ;
// ️ Important: z.infer returns the OUTPUT type!
type input = z . input < typeof stringToNumber > ; // string
type output = z . output < typeof stringToNumber > ; // number
// equivalent to z.output!
type inferred = z . infer < typeof stringToNumber > ; // number
TypeScript Genericsを使用すると、ZODスキーマをパラメーターとして受け入れる再利用可能な関数を記述できます。これにより、タイプの安全性と推論を維持しながら、カスタム検証ロジック、スキーマ変換などを作成できます。
ZODスキーマを入力として受け入れる関数を書き込もうとするとき、このようなことを試してみたいと思うのは魅力的です。
function inferSchema < T > ( schema : z . ZodType < T > ) {
return schema ;
}
このアプローチは正しくなく、タイプスクリプトの引数を適切に推測する能力を制限します。何を渡しても、 schema
のタイプはZodType
のインスタンスになります。
inferSchema ( z . string ( ) ) ;
// => ZodType<string>
This approach loses type information, namely which subclass the input actually is (in this case, ZodString
). That means you can't call any string-specific methods like .min()
on the result of inferSchema
.
A better approach is to infer the schema as a whole instead of merely its inferred type. You can do this with a utility type called z.ZodTypeAny
.
function inferSchema < T extends z . ZodTypeAny > ( schema : T ) {
return schema ;
}
inferSchema ( z . string ( ) ) ;
// => ZodString
ZodTypeAny
is just a shorthand forZodType<any, any, any>
, a type that is broad enough to match any Zod schema.
The Result is now fully and properly typed, and the type system can infer the specific subclass of the schema.
If you follow the best practice of using z.ZodTypeAny
as the generic parameter for your schema, you may encounter issues with the parsed data being typed as any
instead of the inferred type of the schema.
function parseData < T extends z . ZodTypeAny > ( data : unknown , schema : T ) {
return schema . parse ( data ) ;
}
parseData ( "sup" , z . string ( ) ) ;
// => any
Due to how TypeScript inference works, it is treating schema
like a ZodTypeAny
instead of the inferred type. You can fix this with a type cast using z.infer
.
function parseData < T extends z . ZodTypeAny > ( data : unknown , schema : T ) {
return schema . parse ( data ) as z . infer < T > ;
// ^^^^^^^^^^^^^^ <- add this
}
parseData ( "sup" , z . string ( ) ) ;
// => string
The ZodType
class has three generic parameters.
class ZodType <
Output = any ,
Def extends ZodTypeDef = ZodTypeDef ,
Input = Output
> { ... }
By constraining these in your generic input, you can limit what schemas are allowable as inputs to your function:
function makeSchemaOptional < T extends z . ZodType < string > > ( schema : T ) {
return schema . optional ( ) ;
}
makeSchemaOptional ( z . string ( ) ) ;
// works fine
makeSchemaOptional ( z . number ( ) ) ;
// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType<string, ZodTypeDef, string>'
Zod provides a subclass of Error called ZodError
. ZodErrors contain an issues
array containing detailed information about the validation problems.
const result = z
. object ( {
name : z . string ( ) ,
} )
. safeParse ( { name : 12 } ) ;
if ( ! result . success ) {
result . error . issues ;
/* [
{
"code": "invalid_type",
"expected": "string",
"received": "number",
"path": [ "name" ],
"message": "Expected string, received number"
}
] */
}
For detailed information about the possible error codes and how to customize error messages, check out the dedicated error handling guide: ERROR_HANDLING.md
Zod's error reporting emphasizes completeness and correctness . If you are looking to present a useful error message to the end user, you should either override Zod's error messages using an error map (described in detail in the Error Handling guide) or use a third-party library like zod-validation-error
You can use the .format()
method to convert this error into a nested object.
const result = z
. object ( {
name : z . string ( ) ,
} )
. safeParse ( { name : 12 } ) ;
if ( ! result . success ) {
const formatted = result . error . format ( ) ;
/* {
name: { _errors: [ 'Expected string, received number' ] }
} */
formatted . name ?. _errors ;
// => ["Expected string, received number"]
}
There are a handful of other widely-used validation libraries, but all of them have certain design limitations that make for a non-ideal developer experience.
https://github.com/hapijs/joi
Doesn't support static type inference ?
https://github.com/jquense/yup
Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.
https://github.com/gcanti/io-ts
io-ts is an excellent library by gcanti. The API of io-ts heavily inspired the design of Zod.
In our experience, io-ts prioritizes functional programming purity over developer experience in many cases. This is a valid and admirable design goal, but it makes io-ts particularly hard to integrate into an existing codebase with a more procedural or object-oriented bias. For instance, consider how to define an object with optional properties in io-ts:
import * as t from "io-ts" ;
const A = t . type ( {
foo : t . string ,
} ) ;
const B = t . partial ( {
bar : t . number ,
} ) ;
const C = t . intersection ( [ A , B ] ) ;
type C = t . TypeOf < typeof C > ;
// returns { foo: string; bar?: number | undefined }
You must define the required and optional props in separate object validators, pass the optionals through t.partial
(which marks all properties as optional), then combine them with t.intersection
.
Consider the equivalent in Zod:
const C = z . object ( {
foo : z . string ( ) ,
bar : z . number ( ) . optional ( ) ,
} ) ;
type C = z . infer < typeof C > ;
// returns { foo: string; bar?: number | undefined }
This more declarative API makes schema definitions vastly more concise.
io-ts
also requires the use of gcanti's functional programming library fp-ts
to parse results and handle errors. This is another fantastic resource for developers looking to keep their codebase strictly functional. But depending on fp-ts
necessarily comes with a lot of intellectual overhead; a developer has to be familiar with functional programming concepts and the fp-ts
nomenclature to use the library.
fp-ts
compatibility[T, ...T[]]
)https://github.com/pelotom/runtypes
Good type inference support.
[T, ...T[]]
)https://github.com/sindresorhus/ow
Ow is focused on function input validation. It's a library that makes it easy to express complicated assert statements, but it doesn't let you parse untyped data. They support a much wider variety of types; Zod has a nearly one-to-one mapping with TypeScript's type system, whereas ow lets you validate several highly-specific types out of the box (eg int32Array
, see full list in their README).
If you want to validate function inputs, use function schemas in Zod! It's a much simpler approach that lets you reuse a function type declaration without repeating yourself (namely, copy-pasting a bunch of ow assertions at the beginning of every function). Also Zod lets you validate your return types as well, so you can be sure there won't be any unexpected data passed downstream.
View the changelog at CHANGELOG.md