https://zod.dev
정적 유형 추론을 통한 TypeScript 우선 스키마 검증
이 문서는 중국어로 번역되었습니다.
npm
(노드/롤빵)에서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는 가능한 한 개발자 친화적으로 설계되었습니다. 목표는 중복 유형 선언을 제거하는 것입니다. ZOD를 사용하면 유효성 검사기를 한 번 선언하면 ZOD는 정적 유형 유형을 자동으로 추론합니다. 간단한 유형을 복잡한 데이터 구조로 쉽게 구성 할 수 있습니다.
다른 위대한 측면 :
.optional()
) 새 인스턴스를 반환합니다모든 수준의 후원은 감사하고 장려됩니다. ZOD를 사용하여 유료 제품을 만든 경우 회사 계층 중 하나를 고려하십시오.
가장 포괄적 인 사용자 관리 플랫폼
clerk.com
|
|
|
|
|
propelauth | 세르 보스 | 스칼라 | trigger.dev |
트랜스 로트 | 무한 | 때림 | cryptojobslist |
솔직한. | 가장 큰 | 스토리 블록 | MUX |
브랜든 바이어 | 지사 브라베스 | 알렉스 요한슨 | 맹렬한 시스템 |
적응할 수 있는 | 아바나 지갑 | Jason Lengstorf | Global Illumination, Inc. |
마스터본 | 라이언 팔머 | 마이클 스위니 | Nextbase |
존중 | 코너 신 노트 | 모하마드-알리 아르비 | Supatool |
꼭대기에 구축되거나 Zod를 기본적으로 지원하는 도구가 점점 늘어나고 있습니다! Zod 위에 도구 나 도서관을 구축 한 경우 Twitter에서 이에 대해 알려 주거나 토론을 시작하십시오. 아래에 추가하고 트윗하겠습니다.
tRPC
: GraphQL이없는 엔드 투 엔드 타입 안전 API를 빌드하십시오.@anatine/zod-nestjs
: nestjs 프로젝트에서 Zod를 사용하는 도우미 방법.zod-endpoints
: 계약 우선 첫 번째 타이핑 엔드 포인트가 Zod. OpenApi 호환.zhttp
: ZOD 입력 및 응답 검증 기능을 갖춘 OpenApi 호환 및 엄격하게 입력 된 HTTP 라이브러리.domain-functions
: 종합 가능한 함수를 사용하여 프레임 워크에서 비즈니스 로직을 분리하십시오. Zod Schemas에 의해 구동되는 끝에서 끝까지 일류 유형의 추론.@zodios/core
: Axios 및 Zod가 뒷받침하는 런타임 및 컴파일 타임 유효성 검사가 포함 된 TypeScript API 클라이언트.express-zod-api
: I/O 스키마 검증 및 사용자 정의 중간 전위를 사용하여 Express 기반 API를 빌드하십시오.tapiduck
: Zod and Express를 가진 엔드 투 엔드 타입 사프 JSON API; TRPC와 비슷하지만 더 간단합니다.koa-zod-router
: ZOD를 사용한 I/O 검증으로 KOA에서 TypeSafe 경로를 만듭니다.zod-sockets
: Zod-powered socket.io I/O 검증 및 내장 Asyncapi 사양이있는 마이크로 프레임 워크 react-hook-form
: REACT 후크 형태를위한 퍼스트 파티 ZOD 리졸버.zod-validation-error
: ZodError
s에서 사용자 친화적 인 오류 메시지를 생성합니다.zod-formik-adapter
: Zod를위한 커뮤니티 관리 형 Formik 어댑터.react-zorm
: ZOD를 사용한 React에 대한 독립형 <form>
생성 및 검증.zodix
: 리믹스 로더 및 작업의 FormData 및 URLSearchparams 용 ZOD 유틸리티.conform
: HTML 형태의 점진적인 향상을위한 TypeSafe Form 검증 라이브러리. Remix 및 Next.js와 함께 작동합니다.remix-params-helper
: 표준 URLSearchParams 및 Remix 앱의 FormData와 ZOD의 통합을 단순화합니다.formik-validator-zod
: Formik과 함께 ZoD를 사용하여 단순화하는 Formik Compliant Validator 라이브러리.zod-i18n-map
: ZOD 오류 메시지 변환에 유용합니다.@modular-forms/solid
: 유효성 검사를 위해 ZOD를 지원하는 solidjs 용 모듈 식 양식 라이브러리.houseform
: 유효성 검사를 위해 ZOD를 사용하는 React Form 라이브러리.sveltekit-superforms
: ZOD 검증이있는 Sveltekit 용 과급 양식 라이브러리.mobx-zod-form
: mobx & zod를 기반으로 한 데이터 우선 형태 빌더.@vee-validate/zod
: zod 스키마 검증을 사용한 vue.js 용 양식 라이브러리.zod-form-renderer
: ZOD 스키마의 자동 인퍼 양식 필드를 사용하여 E2E 유형 안전성과 반응-쿠크 형식으로 렌더링합니다. zod-to-ts
: ZoD Schemas에서 TypeScript 정의를 생성합니다.zod-to-json-schema
: ZOD 스키마를 JSON 스키마로 변환하십시오.@anatine/zod-openapi
: ZOD 스키마를 OpenAPI v3.x SchemaObject
로 변환합니다.zod-fast-check
: Zod Schemas에서 fast-check
중재를 생성합니다.zod-dto
: ZOD 스키마에서 Nest.js DTOS를 생성합니다.fastify-type-provider-zod
: Zod Schemas에서 Fastify 유형 제공 업체를 작성하십시오.zod-to-openapi
: 스키마, 엔드 포인트 및 매개 변수를 포함하여 ZOD에서 전체 OpenApi (Swagger) 문서를 생성합니다.nestjs-graphql-zod
: Zod Schemas에서 Nestjs GraphQL 모델 클래스를 생성합니다. ZOD 스키마로 작업하는 GraphQL 메소드 데코레이터를 제공합니다.zod-openapi
: ZOD Schemas에서 전체 OpenApi v3.x 문서를 작성하십시오.fastify-zod-openapi
: Zod Schemas에 대한 Fastify 유형 제공자, 검증, 직렬화 및 @Fastify/Swagger 지원.typeschema
: 스키마 검증을위한 범용 어댑터.zodex
: (DE) ZOD Schemas의 직렬화 ts-to-zod
: TypeScript 정의를 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 Schemas를 방출하십시오.drizzle-zod
: 이슬비 스키마에서 Zod 스키마를 방출하십시오.prisma-trpc-generator
: ZOD를 사용하여 완전히 구현 된 TRPC 라우터 및 유효성 검사 스키마를 방출합니다.zod-prisma-types
Prisma 모델에서 ZOD 유형을 만듭니다.quicktype
: JSON 객체와 JSON Schemas를 ZOD 스키마로 변환합니다.@sanity-typed/zod
: Sanity Schemas에서 Zod Schemas를 생성합니다.java-to-zod
: Pojos를 Zod Schemas로 변환하십시오Orval
: OpenApi Schemas에서 ZOD 스키마를 생성합니다Kubb
: OpenAPI Schemas에서 SDK 및 ZOD 스키마 생성 @anatine/zod-mock
: ZOD 스키마에서 모의 데이터를 생성합니다. faker.js에 의해 구동.zod-mocking
: ZoD 스키마에서 모의 데이터를 생성합니다.zod-fixture
: ZOD 스키마를 사용하여 비 관련 테스트 비품 생성을 결정적으로 자동으로 자동화하십시오.zocker
: 스키마에서 그럴듯한 모의 데이터를 생성하십시오.zodock
ZOD 스키마를 기반으로 모의 데이터를 생성합니다.zod-schema-faker
Zod Schemas에서 모의 데이터를 생성합니다. @faker-js/faker 및 randexp.js에 의해 구동됩니다 freerstore
: FIRESTORE COST OPTIMIZER.slonik
: Node.js Postgres 클라이언트가 강력한 ZoD 통합이 있습니다.schemql
: 원시 SQL과 대상 유형 안전 및 스키마 검증을 결합하여 SQL 워크 플로우를 향상시킵니다.soly
: ZOD로 CLI 응용 프로그램을 만듭니다.pastel
: React, Zod 및 Ink를 사용하여 CLI 응용 프로그램을 만듭니다.zod-xlsx
: ZOD Schemas를 사용하는 XLSX 기반 리소스 유효성 검사기.znv
: ZOD Schemas를 사용한 Node.js의 유형 안전 환경 구문 분석 및 유효성 검사.zod-config
: 유연한 어댑터를 사용하여 여러 소스에서 구성을로드하여 ZOD를 사용한 유형 안전을 보장합니다.unplugin-environment
: 스키마 유효성 검사를 통해 주변 변수를 안전하게로드하기위한 플러그인, 가상 모듈로 간단하고 지능형 DX를 사용한 유형 안전? Zod에 의해 구동됩니다. zod_utilz
: ZOD를위한 프레임 워크의 비공식 유틸리티.zod-playground
: ZOD 스키마 검증 기능 학습 및 테스트 도구. 링크.zod-sandbox
: ZOD 스키마 테스트를위한 제어 환경. 라이브 데모.zod-dev
: 제작에서 조종사 런타임 구문 분석을 조건부 비활성화합니다.zod-accelerator
: Zod의 처리량을 최대 ~ 100x까지 가속화합니다. TypeScript 4.5+!
tsconfig.json
에서 strict
모드를 활성화해야합니다. 이것은 모든 TypeScript 프로젝트의 모범 사례입니다.
// 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)에서노드와 달리 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"
구문 분석 단계에서 입력은 String()
함수를 통해 전달됩니다.이 기능은 데이터를 문자열로 강요하기위한 JavaScript 내장입니다.
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
로 설정하여 TimeZone 오프셋을 허용 할 수 있습니다.
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
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
선택적으로, 두 번째 인수를 전달하여 사용자 정의 오류 메시지를 제공 할 수 있습니다.
z . number ( ) . lte ( 5 , { message : "this?is?too?big" } ) ;
ZOD에는 소수의 큰 비인간적 검증이 포함되어 있습니다.
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" ,
} ) ;
Date
인스턴스를 확인하려면 z.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
속성을 사용하십시오.
FishEnum . enum . Salmon ; // => autocompletes
FishEnum . enum ;
/*
=> {
Salmon: "Salmon",
Tuna: "Tuna",
Trout: "Trout",
}
*/
옵션 목록을 .options
속성과 함께 튜플로 검색 할 수도 있습니다.
FishEnum . options ; // ["Salmon", "Tuna", "Trout"];
.exclude/.extract()
.exclude
및 .extract
메소드를 사용하여 ZOD 열거의 서브 세트를 만들 수 있습니다.
const FishEnum = z . enum ( [ "Salmon" , "Tuna" , "Trout" ] ) ;
const SalmonAndTrout = FishEnum . extract ( [ "Salmon" , "Trout" ] ) ;
const TunaOnly = FishEnum . exclude ( [ "Salmon" , "Trout" ] ) ;
ZOD 열거는 열거를 정의하고 검증하는 권장되는 접근법입니다. 그러나 타사 라이브러리에서 열거에 대해 검증 해야하는 경우 (또는 기존 열거를 다시 작성하지 않으려면) 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
typecript 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
.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()
로 무효 유형을 만들 수 있습니다.
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 }
두 스키마가 키를 공유하는 경우 B의 속성은 A의 속성을 무시합니다. 반환 된 스키마는 또한 "UnknownKeys"정책 (Strip/strict/Passthrough)과 B의 포획 스키마를 상속합니다.
.pick/.omit
TypeScrip의 내장 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
내장형 TypeScript 유틸리티 유형 부분에서 영감을 얻은 .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
.partial
방법은 얕습니다. 단 하나의 깊이 만 적용됩니다. "딥"버전도 있습니다.
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 Object Schemas는 구문 분석 중에 인식되지 않은 키를 제거합니다.
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 Object Schemas는 구문 분석 중에 인식되지 않은 키를 제거합니다. .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()
사용하여 .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()
와 달리이 방법은 유추 된 유형을 변경하지 않습니다.
어레이와 달리 튜플에는 고정 된 수의 요소가 있으며 각 요소는 다른 유형을 가질 수 있습니다.
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 오류에 표시됩니다. 반면에 차별화 된 노조는 "옵션"중 하나만 선택하고 테스트 하고이 "옵션"과 관련된 문제 만 표시 할 수 있습니다.
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<...>]
두 개 이상의 차별화 된 노조를 병합하려면 파괴와 함께 .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 유형 Record<number, any>
나타내는 것은 어렵습니다.
결과적으로 [k: number]
둘러싼 TypeScript의 동작은 직관적이지 않습니다.
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
교차로는 "논리 및"유형을 만드는 데 유용합니다. 이것은 두 객체 유형을 교차하는 데 유용합니다.
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)
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 ( ) ) ;
"파싱"은 약속 스키마와 조금 다르게 작동합니다. 유효성 검사는 두 부분으로 이루어집니다.
.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가 공극 회복 함수의 유형을 올바르게 추론 할 수 있습니다. (무효 회복 함수는 실제로 정의되지 않은 반환입니다.)
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 Docs를 읽으십시오.)
그러나 때로는 구문 분석이 발생하기 전에 입력에 약간의 변환을 적용하고 싶습니다. 공통 사용 사례 : 유형 강요. zod는 z.preprocess()
로 이것을 활성화합니다.
const castToString = z . preprocess ( ( val ) => String ( val ) , z . string ( ) ) ;
ZodEffects
인스턴스를 반환합니다. ZodEffects
는 전처리, 개선 및 변환과 관련된 모든 논리를 포함하는 래퍼 클래스입니다.
z.custom()
사용하여 모든 TypeScript 유형에 대한 ZOD 스키마를 만들 수 있습니다. 이것은 템플릿 문자 리터럴과 같이 상자에서 Zod에서 지원하지 않는 유형에 대한 Schemas를 작성하는 데 유용합니다.
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
의 Params 매개 변수와 동일한 방식으로 작동합니다.
z . custom < ... > ( ( val ) => ... , "custom error message" ) ;
모든 ZOD 스키마에는 특정 방법이 포함되어 있습니다.
.parse
.parse(data: unknown): T
ZOD 스키마가 주어지면 .parse
메소드를 호출하여 data
유효합니다. 그렇다면 전체 유형 정보로 값이 반환됩니다! 그렇지 않으면 오류가 발생합니다.
중요 :
.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" ) ;
편의상 .spa
와 별명이 있습니다.
await stringSchema . spa ( "billie" ) ;
.refine
.refine(validator: (data:T)=>any, params?: RefineParams)
ZOD를 사용하면 정제를 통해 사용자 정의 검증 로직을 제공 할 수 있습니다. (여러 문제 생성 및 오류 코드 사용자 정의와 같은 고급 기능의 경우 .superRefine
참조하십시오.)
Zod는 가능한 한 가깝게 TypeScript를 미러링하도록 설계되었습니다. 그러나 TypeScript 유형 시스템에서 표현할 수없는 소위 "정제 유형"이 많이 있습니다. 예를 들어 : 숫자가 정수이거나 문자열이 유효한 이메일 주소인지 확인합니다.
예를 들어 .refine
사용하여 모든 ZOD 스키마에서 사용자 정의 유효성 검사 검사를 정의 할 수 있습니다.
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"
} ]
}
개선은 비동기적 일 수 있습니다.
const userId = z . string ( ) . refine ( async ( id ) => {
// verify that ID exists in database
return true ;
} ) ;
켈 비동기 정제를 사용하는 경우.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
위의 stringToNumber
는 ZodEffects
서브 클래스의 인스턴스입니다. ZodString
의 사례가 아닙니다. 내장 된 ZodString
(예 : .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 () 또는 .safeparesync ()를 사용해야합니다. 그렇지 않으면 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
.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는 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의 유형 시스템은 구조적이므로 구조적으로 동등한 두 가지 유형이 동일하게 간주됩니다.
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>
이 메소드는 기본 스키마를 사용하여 입력을 구문 분석 한 다음 결과에서 Object.freeze()
호출하는 ZodReadonly
스키마 인스턴스를 반환합니다. 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>
로 모든 스키마의 TypeScript 유형을 추출 할 수 있습니다.
const A = z . string ( ) ;
type A = z . infer < typeof A > ; // string
const u : A = 12 ; // TypeError
const u : A = "asdf" ; // compiles
변환은 어떻습니까?
실제로 각 ZOD 스키마는 내부적으로 입력과 출력의 두 가지 유형을 추적합니다. 대부분의 스키마 (예 : 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 enderics를 사용하면 ZOD 스키마를 매개 변수로 받아들이는 재사용 가능한 기능을 작성할 수 있습니다. 이를 통해 유형 안전 및 추론을 유지하면서 사용자 정의 검증 로직, 스키마 변환 등을 만들 수 있습니다.
ZOD 스키마를 입력으로 받아들이는 기능을 작성하려고 할 때 다음과 같은 것을 시도하고 싶은 유혹이 있습니다.
function inferSchema < T > ( schema : z . ZodType < T > ) {
return schema ;
}
이 접근법은 부정확하며 TypeScript의 인수를 올바르게 추론하는 능력을 제한합니다. 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