https://zod.dev
การตรวจสอบความถูกต้องของสคี
เอกสารเหล่านี้ได้รับการแปลเป็นภาษาจีน
npm
(Node/Bun)deno.land/x
(deno).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 เป็นสคีมาสคีมา TypeScript และไลบรารีการตรวจสอบความถูกต้อง ฉันใช้คำว่า "สคีมา" เพื่ออ้างถึงชนิดข้อมูลใด ๆ จาก string
ง่าย ๆ ไปจนถึงวัตถุซ้อนที่ซับซ้อน
Zod ได้รับการออกแบบให้เป็นมิตรกับนักพัฒนามากที่สุด The goal is to eliminate duplicative type declarations. ด้วย ZOD คุณจะประกาศตัวตรวจสอบความถูกต้อง หนึ่งครั้ง และ ZOD จะอนุมานประเภท typescript แบบคงที่โดยอัตโนมัติ ง่ายต่อการเขียนประเภทที่ง่ายกว่าลงในโครงสร้างข้อมูลที่ซับซ้อน
แง่มุมที่ยอดเยี่ยมอื่น ๆ :
.optional()
) ส่งคืนอินสแตนซ์ใหม่การสนับสนุนในทุกระดับจะได้รับการชื่นชมและสนับสนุน หากคุณสร้างผลิตภัณฑ์ที่ชำระเงินโดยใช้ ZOD ให้พิจารณาหนึ่งในระดับองค์กร
แพลตฟอร์มการจัดการผู้ใช้ที่ครอบคลุมที่สุด
Clerk.com
|
|
|
|
|
ผู้จัดทำ | Cerbos | ตาชั่ง | trigger.dev |
การขนถ่าย | เกี่ยวกับโรคระบาด | ชรา | Cryptojobslist |
ธรรมดา. | ที่ได้รับความนิยมมากที่สุด | Storyblok | MUX |
แบรนดอนไบเออร์ | Jiří Brabec | Alex Johansson | ระบบ fungible |
ปรับได้ | Avana Wallet | Jason Lengstorf | Global Illumination, Inc. |
มาสเตอร์บอร์น | ไรอันพาลเมอร์ | Michael Sweeney | Nextbase |
Remotion | Connor Sinnott | Mohammad-ali a'râbi | supatool |
มีเครื่องมือจำนวนมากขึ้นที่สร้างขึ้นบนยอดหรือสนับสนุน Zod โดยธรรมชาติ! หากคุณได้สร้างเครื่องมือหรือห้องสมุดที่ด้านบนของ ZOD บอกฉันเกี่ยวกับเรื่องนี้บน Twitter หรือเริ่มการสนทนา ฉันจะเพิ่มด้านล่างและทวีตออก
tRPC
: สร้าง API แบบ end-to-end API โดยไม่มี GraphQL@anatine/zod-nestjs
: วิธีการช่วยสำหรับการใช้ ZOD ในโครงการ NestJSzod-endpoints
: สัญญาก่อนพิมพ์จุดสิ้นสุดอย่างเคร่งครัดกับ ZOD OpenAPI compatible.zhttp
: ไลบรารี HTTP ที่เข้ากันได้ OpenAPI พิมพ์อย่างเคร่งครัดพร้อมกับการป้อนข้อมูล ZOD และการตรวจสอบการตอบสนองdomain-functions
: ถอดตรรกะทางธุรกิจของคุณจากเฟรมเวิร์กของคุณโดยใช้ฟังก์ชั่นคอมโพสิต ด้วยการอนุมานประเภทชั้นหนึ่งตั้งแต่ต้นจนจบโดย Zod Schemas@zodios/core
: ไคลเอนต์ TypeScript API ที่มีรันไทม์และการตรวจสอบเวลาคอมไพล์ที่ได้รับการสนับสนุนโดย Axios และ Zodexpress-zod-api
: สร้าง APIs แบบด่วนพร้อมการตรวจสอบสคีมา I/O และ Middlewares ที่กำหนดเองtapiduck
: APIs JSON แบบ end-to-end กับ Zod และ Express; a bit like tRPC, but simpler.koa-zod-router
: สร้างเส้นทาง typesafe ใน KOA ด้วยการตรวจสอบ I/O โดยใช้ ZODzod-sockets
: zod-powered socket.io microframework พร้อมการตรวจสอบ I/O และ specs asyncapi ในตัว react-hook-form
: ตัวแก้ไข ZOD ของบุคคลแรกสำหรับแบบฟอร์ม React Hookzod-validation-error
: สร้างข้อความแสดงข้อผิดพลาดที่ใช้งานง่ายจาก ZodError
szod-formik-adapter
: อะแดปเตอร์ Formik ที่ได้รับการดูแลจากชุมชนสำหรับ Zodreact-zorm
: Standalone <form>
generation and validation for React using Zod.zodix
: zod ยูทิลิตี้สำหรับ formdata และ urlsearchparams ใน remix loaders และการกระทำconform
: ไลบรารีการตรวจสอบแบบฟอร์ม typesafe สำหรับการปรับปรุงแบบก้าวหน้าของรูปแบบ HTML ทำงานกับ Remix และ Next.jsremix-params-helper
: ทำให้การรวม ZOD ง่ายขึ้นกับ URLSearchParams มาตรฐานและ formData สำหรับแอพเรียบเรียงformik-validator-zod
: ไลบรารี Validator ที่สอดคล้องกับ Formik ที่ทำให้ง่ายขึ้นโดยใช้ ZOD ด้วย formikzod-i18n-map
: มีประโยชน์สำหรับการแปลข้อความแสดงข้อผิดพลาด ZOD@modular-forms/solid
: Modular Form Library สำหรับ SolidJs ที่รองรับ ZOD สำหรับการตรวจสอบความถูกต้องhouseform
: ไลบรารีแบบฟอร์ม React ที่ใช้ ZOD เพื่อตรวจสอบความถูกต้องsveltekit-superforms
: ห้องสมุดฟอร์ม supercharged สำหรับ sveltekit พร้อมการตรวจสอบ ZODmobx-zod-form
: Builder Form Form Data-First ตาม MOBX & ZOD@vee-validate/zod
: ฟอร์มไลบรารีสำหรับ vue.js พร้อมการตรวจสอบความถูกต้องของ zod schemazod-form-renderer
: ฟิลด์ฟอร์มแบบอินเทอร์อัตโนมัติจาก ZOD Schema และแสดงผลด้วย React-Hook-Form พร้อมความปลอดภัยประเภท E2E zod-to-ts
: สร้างคำจำกัดความ TypeScript จาก Zod Schemaszod-to-json-schema
: แปลง zod schemas ของคุณเป็น json schemas@anatine/zod-openapi
: Converts a Zod schema to an OpenAPI v3.x SchemaObject
.zod-fast-check
: สร้าง fast-check
จาก zod schemaszod-dto
: สร้าง Nest.js DTOs จาก Schema Zodfastify-type-provider-zod
: สร้างผู้ให้บริการประเภท Fastify จาก Zod Schemaszod-to-openapi
: สร้างเอกสาร OpenAPI (Swagger) เต็มรูปแบบจาก ZOD รวมถึง Schemas, จุดสิ้นสุดและพารามิเตอร์nestjs-graphql-zod
: สร้างคลาสโมเดล NESTJS GraphQl จาก Zod Schemas ให้วิธีการ graphql decorators ที่ทำงานกับ zod schemaszod-openapi
: Create full OpenAPI v3.x documentation from Zod schemas.fastify-zod-openapi
: ผู้ให้บริการประเภท Fastify, การตรวจสอบ, การทำให้เป็นอนุกรมและ @fastify/swagger รองรับ zod schemastypeschema
: อะแดปเตอร์สากลสำหรับการตรวจสอบสคีมาzodex
: (de) serialization สำหรับ zod schemas ts-to-zod
: แปลงคำจำกัดความ TypeScript เป็น zod schemas@runtyping/zod
: สร้าง zod จากประเภทคงที่ & json schemajson-schema-to-zod
: แปลง Schemas JSON ของคุณเป็น zod schemas การสาธิตสดjson-to-zod
: แปลงวัตถุ JSON เป็น zod schemas การสาธิตสดgraphql-codegen-typescript-validation-schema
: GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.zod-prisma
: สร้าง zod schemas จาก Schema Prisma ของคุณSupervillain
: สร้าง zod schemas จาก go structs ของคุณprisma-zod-generator
: ปล่อย Zod Schemas จาก Schema Prisma ของคุณdrizzle-zod
: ปล่อย Zod Schemas จากสคีมาของคุณprisma-trpc-generator
: ปล่อยเราเตอร์ TRPC ที่ใช้งานอย่างเต็มที่และ schemas การตรวจสอบความถูกต้องของพวกเขาโดยใช้ ZODzod-prisma-types
สร้างประเภท ZOD จากรุ่น Prisma ของคุณquicktype
: แปลงวัตถุ JSON และ Schemas JSON เป็น zod schemas@sanity-typed/zod
: สร้าง zod schemas จาก Sanity Schemasjava-to-zod
: แปลง pojos เป็น zod schemasOrval
: สร้าง zod schemas จาก openapi schemasKubb
: สร้าง SDKS และ ZOD Schema จาก OpenAPI Schemas ของคุณ @anatine/zod-mock
: สร้างข้อมูลจำลองจาก zod schema ขับเคลื่อนโดย faker.jszod-mocking
: สร้างข้อมูลจำลองจาก zod schemas ของคุณzod-fixture
: Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.zocker
: Generate plausible mock-data from your schemas.zodock
สร้างข้อมูลจำลองตาม zod schemaszod-schema-faker
สร้างข้อมูลจำลองจาก Zod Schemas ขับเคลื่อนโดย @faker-js/faker และ randexp.js freerstore
: Optimizer ต้นทุน Firestoreslonik
: node.js postgres ไคลเอนต์ที่มีการรวม ZOD ที่แข็งแกร่งschemql
: ปรับปรุงเวิร์กโฟลว์ SQL ของคุณโดยการรวม SQL ดิบเข้ากับความปลอดภัยประเภทเป้าหมายและการตรวจสอบความถูกต้องของสคีมาsoly
: สร้างแอปพลิเคชัน CLI ด้วย ZODpastel
: สร้างแอปพลิเคชัน CLI ด้วย React, Zod และ Inkzod-xlsx
: ตัวตรวจสอบทรัพยากรที่ใช้ XLSX โดยใช้ zod schemasznv
: Type-safe environment parsing and validation for Node.js with Zod schemas.zod-config
: โหลดการกำหนดค่าในหลาย ๆ แหล่งด้วยอะแดปเตอร์ที่ยืดหยุ่นเพื่อให้มั่นใจถึงความปลอดภัยของประเภทด้วย ZODunplugin-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
: Utilities Agnostic Framework สำหรับ Zodzod-playground
: เครื่องมือสำหรับการเรียนรู้และทดสอบฟังก์ชั่นการตรวจสอบความถูกต้องของ ZOD ลิงค์.zod-sandbox
: สภาพแวดล้อมที่ควบคุมสำหรับการทดสอบ zod schemas Live demo.zod-dev
: Conditionally disables Zod runtime parsing in production.zod-accelerator
: เร่งความเร็วของ ZOD สูงถึง ~ 100x TypeScript 4.5+!
คุณต้องเปิดใช้งานโหมด strict
ใน tsconfig.json
ของคุณ นี่เป็นแนวทางปฏิบัติที่ดีที่สุดสำหรับโครงการ TypeScript ทั้งหมด
// tsconfig.json
{
// ...
"compilerOptions" : {
// ...
"strict" : true
}
}
npm
(Node/Bun) npm install zod # npm
yarn add zod # yarn
bun add zod # bun
pnpm add zod # pnpm
Zod ยังเผยแพร่เวอร์ชัน Canary ในทุกการกระทำ ในการติดตั้ง Canary:
npm install zod@canary # npm
yarn add zod@canary # yarn
bun add zod@canary # bun
pnpm add zod@canary # pnpm
deno.land/x
(deno)ซึ่งแตกต่างจาก Node, Deno อาศัยการนำเข้า URL โดยตรงแทนที่จะเป็นผู้จัดการแพ็คเกจเช่น NPM 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"
ในระหว่างขั้นตอนการแยกวิเคราะห์อินพุตจะถูกส่งผ่านฟังก์ชั่น String()
ซึ่งเป็นจาวาสคริปต์ในตัวสำหรับการบังคับข้อมูลลงในสตริง
schema . parse ( 12 ) ; // => "12"
schema . parse ( true ) ; // => "true"
schema . parse ( undefined ) ; // => "undefined"
schema . parse ( null ) ; // => "null"
สคีมาที่ส่งคืนเป็นอินสแตน ZodString
ปกติเพื่อให้คุณสามารถใช้วิธีการสตริงทั้งหมด
z . coerce . string ( ) . email ( ) . min ( 5 ) ;
How coercion works
ประเภทดั้งเดิมทั้งหมดรองรับการบีบบังคับ zod coerces อินพุตทั้งหมดโดยใช้ตัวสร้างในตัว: 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()
schemas ตัวอักษรเป็นตัวแทนประเภทตัวอักษรเช่น "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 สำหรับฟังก์ชั่นการตรวจสอบสตริงที่มีประโยชน์อื่น ๆ ที่สามารถใช้ร่วมกับการปรับแต่งได้
You can customize some common error messages when creating a string schema.
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)
Timezone offsets can be allowed by setting the offset
option to 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+]
ที่สองสามารถรวมถึงความแม่นยำของทศนิยมโดยพลการ ไม่อนุญาตให้มีการชดเชยเขตเวลาใด ๆ
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
คุณสามารถตั้งค่า version
IP เพิ่มเติมได้
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
ทางเลือกคุณสามารถส่งผ่านในอาร์กิวเมนต์ที่สองเพื่อให้ข้อความแสดงข้อผิดพลาดที่กำหนดเอง
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 Schema
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!" } ) ;
Coercion to Date
ตั้งแต่ 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
เพื่อกำหนดค่า enum ของคุณเป็น tuple ของสตริง ดูรายละเอียดเอกสารการยืนยัน
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",
}
*/
นอกจากนี้คุณยังสามารถดึงรายการตัวเลือกเป็น tuple ด้วยคุณสมบัติ .options
:
FishEnum . options ; // ["Salmon", "Tuna", "Trout"];
.exclude/.extract()
คุณสามารถสร้างชุดย่อยของ zod enum ด้วย .exclude
และ .extract
extract
const FishEnum = z . enum ( [ "Salmon" , "Tuna" , "Trout" ] ) ;
const SalmonAndTrout = FishEnum . extract ( [ "Salmon" , "Trout" ] ) ;
const TunaOnly = FishEnum . exclude ( [ "Salmon" , "Trout" ] ) ;
Zod enums เป็นวิธีที่แนะนำในการกำหนดและตรวจสอบความถูกต้องของ enums แต่ถ้าคุณต้องการตรวจสอบความถูกต้องกับ enum จากห้องสมุดบุคคลที่สาม (หรือคุณไม่ต้องการเขียน enums ที่มีอยู่ของคุณใหม่) คุณสามารถใช้ z.nativeEnum()
enums ตัวเลข
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
enums สตริง
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
ต้องการ TypeScript 3.4+!
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
You can access the underlying object with the .enum
property:
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 };
คุณสามารถแยกสคีมาที่ห่อหุ้มออกจากอินสแตนซ์ ZodOptional
ด้วย .unwrap()
const stringSchema = z . string ( ) ;
const optionalString = stringSchema . optional ( ) ;
optionalString . unwrap ( ) === stringSchema ; // true
ในทำนองเดียวกันคุณสามารถสร้างประเภทที่ว่างได้ด้วย z.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
เพื่อเข้าถึง schemas สำหรับคีย์เฉพาะ
Dog . shape . name ; // => string schema
Dog . shape . age ; // => number schema
.keyof
ใช้ .keyof
เพื่อสร้าง ZodEnum
schema จากปุ่มของสคีมาวัตถุ
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 }
หากทั้งสอง schemas แบ่งปันคีย์คุณสมบัติของ B แทนที่คุณสมบัติของ A. Schema ที่ส่งคืนจะสืบทอดนโยบาย "unknownkeys" (แถบ/เข้มงวด/passthrough) และ schema catchall ของ B.
.pick/.omit
แรงบันดาลใจจากประเภทยูทิลิ Pick
ที่เลือกในตัวของ TypeScript และแบบใช้ประโยชน์ของ Omit
Schemas Object 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
ได้รับแรงบันดาลใจจากประเภท Utility Typeint ในตัวบางส่วนวิธีการ .partial
ส่วนที่ทำให้คุณสมบัติทั้งหมดเป็นตัวเลือก
เริ่มต้นจากวัตถุนี้:
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
The .partial
method is shallow — it only applies one level deep. นอกจากนี้ยังมีเวอร์ชัน "ลึก":
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}[]
}
*/
ข้อ จำกัด ที่สำคัญ: ส่วนลึกทำงานเฉพาะตามที่คาดไว้ในลำดับชั้นของวัตถุอาร์เรย์และ tuples
.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
โดยค่าเริ่มต้น Schemas Object Object จะตัดปุ่มที่ไม่รู้จักระหว่างการแยกวิเคราะห์
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
โดยค่าเริ่มต้น Schemas Object Object จะตัดปุ่มที่ไม่รู้จักระหว่างการแยกวิเคราะห์ คุณสามารถ ไม่อนุญาต คีย์ที่ไม่รู้จักด้วย .strict()
หากมีคีย์ที่ไม่รู้จักในอินพุต ZOD จะโยนข้อผิดพลาด
const person = z
. object ( {
name : z . string ( ) ,
} )
. strict ( ) ;
person . parse ( {
name : "bob dylan" ,
extraKey : 61 ,
} ) ;
// => throws ZodError
.strip
คุณสามารถใช้วิธี .strip
เพื่อรีเซ็ตสคีมาวัตถุเป็นพฤติกรรมเริ่มต้น (การลอกปุ่มที่ไม่รู้จัก)
.catchall
คุณสามารถส่งสคีมา "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()
obviates .passthrough()
, .strip()
หรือ .strict()
คีย์ทั้งหมดได้รับการพิจารณาว่า "เป็นที่รู้จัก"
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
หากคุณต้องการให้แน่ใจว่าอาร์เรย์มีองค์ประกอบอย่างน้อยหนึ่งองค์ประกอบให้ใช้ .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()
วิธีการเหล่านี้ไม่ได้เปลี่ยนประเภทที่อนุมาน
ซึ่งแตกต่างจากอาร์เรย์ tuples มีจำนวนองค์ประกอบคงที่และแต่ละองค์ประกอบสามารถมีประเภทที่แตกต่างกัน
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 }]
สามารถเพิ่มอาร์กิวเมนต์ Variadic ("REST") ด้วยวิธี. .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 ( ) ) ;
Optional string validation:
ในการตรวจสอบความถูกต้องของอินพุตฟอร์มเสริมคุณสามารถรวมการตรวจสอบความถูกต้องของสตริงที่ต้องการด้วยตัวอักษรสตริงที่ว่างเปล่า
ตัวอย่างนี้ตรวจสอบอินพุตที่เป็นตัวเลือก แต่ต้องมี 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
สหภาพที่ถูกเลือกปฏิบัติคือสหภาพของ schemas วัตถุที่ทั้งหมดแบ่งปันคีย์เฉพาะ
type MyUnion =
| { status : "success" ; data : string }
| { status : "failed" ; error : Error } ;
สหภาพดังกล่าวสามารถแสดงด้วยวิธี z.discriminatedUnion
สิ่งนี้ช่วยให้การประเมินผลเร็วขึ้นเนื่องจาก ZOD สามารถตรวจสอบ คีย์ discriminator ( status
ในตัวอย่างด้านบน) เพื่อกำหนดว่าควรใช้สคีมาใดในการแยกวิเคราะห์อินพุต สิ่งนี้ทำให้การแยกวิเคราะห์มีประสิทธิภาพมากขึ้นและทำให้ ZOD รายงานข้อผิดพลาดที่เป็นมิตร
ด้วยวิธีการยูเนี่ยนพื้นฐานอินพุตจะถูกทดสอบกับแต่ละตัวเลือกที่ให้ไว้ "และในกรณีของการไม่ถูกต้องปัญหาสำหรับ" ตัวเลือก "ทั้งหมดจะแสดงในข้อผิดพลาดของ ZOD ในทางกลับกันสหภาพที่ถูกเลือกปฏิบัติอนุญาตให้เลือกเพียงหนึ่งใน "ตัวเลือก" การทดสอบและแสดงเฉพาะปัญหาที่เกี่ยวข้องกับ "ตัวเลือก" นี้
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" } ) ;
คุณสามารถแยกการอ้างอิงไปยังอาร์เรย์ของ schemas ด้วยคุณสมบัติ. .options
myUnion . options ; // [ZodObject<...>, ZodObject<...>]
ในการรวมสหภาพที่ถูกเลือกปฏิบัติสองครั้งขึ้นไปให้ใช้. .options
กับการทำลายโครงสร้าง
const A = z . discriminatedUnion ( "status" , [
/* options */
] ) ;
const B = z . discriminatedUnion ( "status" , [
/* options */
] ) ;
const AB = z . discriminatedUnion ( "status" , [ ... A . options , ... B . options ] ) ;
SCHEMA บันทึกใช้เพื่อตรวจสอบประเภทเช่น 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>
มันยากที่จะแสดงประเภท typeScript ประเภท Record<number, any>
ใน ZOD
ตามที่ปรากฎพฤติกรรมของ TypeScript โดยรอบ [k: number]
นั้นไม่ได้ใช้งานง่ายเล็กน้อย:
const testMap : { [ k : number ] : string } = {
1 : "one" ,
} ;
for ( const key in testMap ) {
console . log ( ` ${ key } : ${ typeof key } ` ) ;
}
// prints: `1: string`
อย่างที่คุณเห็น JavaScript จะหล่อปุ่มวัตถุทั้งหมดไปยังสตริงโดยอัตโนมัติภายใต้ประทุน เนื่องจาก Zod พยายามเชื่อมช่องว่างระหว่างประเภทคงที่และแบบรันไทม์จึงไม่สมเหตุสมผลที่จะให้วิธีการสร้างสคีมาบันทึกด้วยคีย์ตัวเลขเนื่องจากไม่มีสิ่งใดเป็นคีย์ตัวเลขในรันไทม์จาวาสคริปต์
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>
ชุด schemas สามารถถูก จำกัด เพิ่มเติมด้วยวิธียูทิลิตี้ต่อไปนี้
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
ทางแยกมีประโยชน์สำหรับการสร้างประเภท "ตรรกะและ" สิ่งนี้มีประโยชน์สำหรับการตัดกันวัตถุสองประเภท
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)
เพื่อรวมวัตถุสองชิ้น วิธี. .merge
ส่งคืนอินสแตนซ์ ZodObject
ใหม่ในขณะที่ A.and(B)
ส่งคืน ZodIntersection
ที่มีประโยชน์น้อยกว่าซึ่งไม่มีวิธีการวัตถุทั่วไปเช่น pick
และ omit
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 แต่เนื่องจากข้อ จำกัด ของ typeitions ประเภทของพวกเขาจึงไม่สามารถอนุมานได้อย่างคงที่ Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".
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.ZodType
กับ z.ZodEffects
( .refine
, .transform
, preprocess
, ฯลฯ ... ) คุณจะต้องกำหนดประเภทอินพุตและเอาต์พุตของสคีมา 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 ที่แนะนำสิ่งนี้
Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop in some cases.
ในการตรวจจับวัตถุวัฏจักรก่อนที่จะก่อให้เกิดปัญหาให้พิจารณาวิธีการนี้
const numberPromise = z . promise ( z . number ( ) ) ;
"การแยกวิเคราะห์" ทำงานแตกต่างกันเล็กน้อยกับ Schemas สัญญา การตรวจสอบความถูกต้องเกิดขึ้นในสองส่วน:
.then
และ .catch
).then
to attach an additional validation step onto the existing Promise. คุณจะต้องใช้ .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 ยังให้คุณกำหนด "ฟังก์ชั่น schemas" สิ่งนี้ทำให้ง่ายต่อการตรวจสอบอินพุตและเอาต์พุตของฟังก์ชั่นโดยไม่ต้องผสมรหัสการตรวจสอบความถูกต้องของคุณและ "ตรรกะทางธุรกิจ"
คุณสามารถสร้างสคีมาฟังก์ชั่นด้วย 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
ฟังก์ชั่น schemas มีวิธี .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 อนุมานประเภทของฟังก์ชั่นการส่งคืนโมฆะได้อย่างถูกต้อง (ฟังก์ชั่นการส่งคืนโมฆะกลับมาไม่ได้กำหนดจริง ๆ )
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 enables this with the z.preprocess()
.
const castToString = z . preprocess ( ( val ) => String ( val ) , z . string ( ) ) ;
สิ่งนี้จะส่งคืนอินสแตน ZodEffects
ZodEffects
เป็นคลาส wrapper ที่มีตรรกะทั้งหมดที่เกี่ยวข้องกับการประมวลผลล่วงหน้าการปรับแต่งและการแปลง
คุณสามารถสร้าง zod schema สำหรับประเภท typescript ใด ๆ โดยใช้ z.custom()
สิ่งนี้มีประโยชน์สำหรับการสร้าง schemas สำหรับประเภทที่ไม่ได้รับการสนับสนุนโดย 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
คุณสามารถปรับแต่งข้อความแสดงข้อผิดพลาดและตัวเลือกอื่น ๆ โดยผ่านอาร์กิวเมนต์ที่สอง พารามิเตอร์นี้ทำงานในลักษณะเดียวกับพารามิเตอร์พารามิเตอร์ของ .refine
z . custom < ... > ( ( val ) => ... , "custom error message" ) ;
zod schemas ทั้งหมดมีวิธีการบางอย่าง
.parse
.parse(data: unknown): T
ด้วย zod schema ใด ๆ คุณสามารถโทรหาวิธี .parse
เพื่อตรวจสอบ data
ที่ถูกต้อง ถ้าเป็นเช่นนั้นค่าจะถูกส่งกลับด้วยข้อมูลประเภทเต็ม! Otherwise, an error is thrown.
สำคัญ: ค่าที่ส่งคืนโดย
.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; }
If you don't want Zod to throw errors when validation fails, use .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 ตัวอย่างเช่น: ตรวจสอบว่าตัวเลขเป็นจำนวนเต็มหรือสตริงเป็นที่อยู่อีเมลที่ถูกต้อง
ตัวอย่างเช่นคุณสามารถกำหนดการตรวจสอบการตรวจสอบความถูกต้องที่กำหนดเองบน zod schema ใด ๆ ด้วย .refine
:
const myString = z . string ( ) . refine ( ( val ) => val . length <= 255 , {
message : "String can't be more than 255 characters" ,
} ) ;
ฟังก์ชั่นการปรับแต่งไม่ควรโยน พวกเขาควรส่งคืนค่าเท็จเพื่อความล้มเหลวของสัญญาณ
อย่างที่คุณเห็น. .refine
ใช้สองข้อโต้แย้ง
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 ;
} ;
สำหรับกรณีขั้นสูงอาร์กิวเมนต์ที่สองอาจเป็นฟังก์ชันที่ส่งคืน 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"
} ]
}
การปรับแต่งยังสามารถเป็น async:
const userId = z . string ( ) . refine ( async ( id ) => {
// verify that ID exists in database
return true ;
} ) ;
หากคุณใช้การปรับแต่ง async คุณต้องใช้วิธี. .parseAsync
เพื่อแยกวิเคราะห์ข้อมูล! มิฉะนั้น Zod จะโยนข้อผิดพลาด
การแปลงและการปรับแต่งสามารถ interleaved:
z . string ( )
. transform ( ( val ) => val . length )
. refine ( ( val ) => val > 25 ) ;
.superRefine
วิธี .refine
เป็นน้ำตาลวากยสัมพันธ์บนวิธีการที่หลากหลาย (และ verbose) ที่เรียกว่า 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
โดยค่าเริ่มต้นการแยกวิเคราะห์จะดำเนินต่อไปแม้หลังจากการตรวจสอบการปรับแต่งล้มเหลว ตัวอย่างเช่นหากคุณรวมการปรับแต่งหลายอย่างเข้าด้วยกันพวกเขาทั้งหมดจะถูกดำเนินการ However, it may be desirable to abort early to prevent later refinements from being executed. เพื่อให้บรรลุสิ่งนี้ให้ส่งธง 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" ,
} ) ;
}
} ) ;
หากคุณจัดเตรียม predicate type ไปยัง .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
โปรดทราบว่า stringToNumber
ด้านบนเป็นอินสแตนซ์ของคลาสย่อย ZodEffects
มันไม่ใช่อินสแตนซ์ของ ZodString
หากคุณต้องการใช้วิธีการในตัวของ ZodString
(เช่น .email()
) คุณต้องใช้วิธีการเหล่านั้น ก่อน การแปลงใด ๆ
const emailToDomain = z
. string ( )
. email ( )
. transform ( ( val ) => val . split ( "@" ) [ 1 ] ) ;
emailToDomain . parse ( "[email protected]" ) ; // => example.com
วิธี .transform
สามารถตรวจสอบและแปลงค่าพร้อมกัน สิ่งนี้มักจะง่ายกว่าและซ้ำซ้อนน้อยกว่า transform
และ refine
As with .superRefine
, the transform function receives a ctx
object with an addIssue
method that can be used to register validation issues.
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 ;
} ) ;
การแปลงและการปรับแต่งสามารถ interleaved สิ่งเหล่านี้จะถูกดำเนินการตามลำดับที่พวกเขาประกาศ
const nameToGreeting = z
. string ( )
. transform ( ( val ) => val . toUpperCase ( ) )
. refine ( ( val ) => val . length > 15 )
. transform ( ( val ) => `Hello ${ val } ` )
. refine ( ( val ) => val . indexOf ( "!" ) === - 1 ) ;
การแปลงอาจเป็น async
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…
สิ่งนี้มีประโยชน์สำหรับการจัดทำเอกสารฟิลด์ตัวอย่างเช่นในสคีมา JSON โดยใช้ไลบรารีเช่น zod-to-json-schema
)
.catch
ใช้ .catch()
เพื่อให้ "ค่าจับ" ที่จะส่งคืนในกรณีที่เกิดข้อผิดพลาดในการแยกวิเคราะห์
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 schemas will accept both undefined
and null
. อ่านเพิ่มเติมเกี่ยวกับแนวคิดของ "Nullish" ในบันทึกย่อการเปิดตัว 3.7
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 เป็นโครงสร้างซึ่งหมายความว่าสองประเภทใด ๆ ที่เทียบเท่าโครงสร้างนั้นถือว่าเหมือนกัน
type Cat = { name : string } ;
type Dog = { name : string } ;
const petCat = ( cat : Cat ) => { } ;
const fido : Dog = { name : "fido" } ;
petCat ( fido ) ; // works fine
ในบางกรณีอาจเป็นที่พึงปรารถนาที่จะจำลอง การพิมพ์เล็กน้อย ภายใน typescript ตัวอย่างเช่นคุณอาจต้องการเขียนฟังก์ชั่นที่ยอมรับเฉพาะอินพุตที่ได้รับการตรวจสอบโดย 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
schema ที่แยกวิเคราะห์อินพุตโดยใช้สคีมาฐานจากนั้นเรียก 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
Schemas สามารถถูกล่ามโซ่ไว้ในการตรวจสอบความถูกต้อง "ท่อ" มันมีประโยชน์สำหรับการตรวจสอบผลลัพธ์ได้อย่างง่ายดายหลังจาก .transform()
:
z . string ( )
. transform ( ( val ) => val . length )
. pipe ( z . number ( ) . min ( 5 ) ) ;
เมธอด .pipe()
ส่งคืนอินสแตนซ์ ZodPipeline
.pipe()
to fix common issues with 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
with constrained input:
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
คุณสามารถแยกประเภท typeScript ของสคีมาใด ๆ ด้วย 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
แล้วการแปลงล่ะ?
ในความเป็นจริงแต่ละ Schema Zod ติดตาม สอง ประเภท: อินพุตและเอาต์พุต สำหรับ schemas ส่วนใหญ่ (เช่น z.string()
) ทั้งสองนี้เหมือนกัน แต่เมื่อคุณเพิ่มการแปลงลงในส่วนผสมแล้วค่าทั้งสองนี้สามารถแตกต่างกันได้ เช่น z.string().transform(val => val.length)
มีอินพุตของ string
และเอาต์พุตของ number
คุณสามารถแยกประเภทอินพุตและเอาต์พุตได้เช่น So:
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 คุณสามารถเขียนฟังก์ชั่นที่นำกลับมาใช้ใหม่ได้ซึ่งยอมรับ SCOD SCHEMA เป็นพารามิเตอร์ สิ่งนี้ช่วยให้คุณสามารถสร้างตรรกะการตรวจสอบความถูกต้องที่กำหนดเองการแปลงสคีมาและอื่น ๆ ในขณะที่รักษาความปลอดภัยและการอนุมานประเภท
เมื่อพยายามเขียนฟังก์ชั่นที่ยอมรับ zod schema เป็นอินพุตมันเป็นสิ่งล่อใจที่จะลองอะไรแบบนี้:
function inferSchema < T > ( schema : z . ZodType < T > ) {
return schema ;
}
This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of schema
will be an instance of 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