UNPKG

zod

Version:

TypeScript-first schema declaration and validation library with static type inference

1,358 lines (1,107 loc) 101 kB
<p align="center"> <img src="https://raw.githubusercontent.com/colinhacks/zod/main/logo.svg" width="200px" align="center" alt="Zod logo" /> <h1 align="center">Zod</h1> <p align="center"> <a href="https://zod.dev">zod.dev</a> <br/> TypeScript-first schema validation with static type inference </p> </p> <p align="center"> <a href="https://github.com/colinhacks/zod/actions?query=branch%3Amain"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=main" alt="Zod CI status" /></a> <a href="https://twitter.com/colinhacks" rel="nofollow"><img src="https://img.shields.io/badge/created%20by-@colinhacks-4BBAAB.svg" alt="Created by Colin McDonnell"></a> <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a> <a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a> <a href="https://github.com/colinhacks/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a> </p> <div align="center"> <a href="https://zod.dev">Website</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="https://discord.gg/RcG33DQJdf">Discord</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="https://twitter.com/colinhacks">𝕏</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="https://bsky.app/profile/zod.dev">Bluesky</a> <br /> </div> <br/><br/> <table align="center" style="justify-content:center;align-items:center;display:flex;"><td> <p align="center">Zod 4 is now in beta! <br/> <a target="_blank" rel="noopener noreferrer" href="https://v4.zod.dev/v4">Read the announcement 👉</a></p></td> </table> <br/> <br/> <h2 align="center">Featured sponsor: Stainless</h2> <div align="center"> <a href="https://www.stainless.com/?utm_source=zod"> <picture width="95%" > <source media="(prefers-color-scheme: dark)" srcset="https://i.imgur.com/bjyoaHY.jpeg"> <img alt="stainless logo" src="https://i.imgur.com/bjyoaHY.jpeg" width="95%"> </picture> </a> <br/> <p><sub>Learn more about <a target="_blank" rel="noopener noreferrer" href="mailto:sponsorship@colinhacks.com">featured sponsorships</a></sub></p> </div> <!-- <hr/> --> <br/> <br/> ## Table of contents > These docs have been translated into [Chinese](./README_ZH.md) and [Korean](./README_KO.md). - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Sponsors](#sponsors) - [Platinum](#platinum) - [Gold](#gold) - [Silver](#silver) - [Bronze](#bronze) - [Copper](#copper) - [Ecosystem](#ecosystem) - [Resources](#resources) - [API libraries](#api-libraries) - [Form integrations](#form-integrations) - [Zod to X](#zod-to-x) - [X to Zod](#x-to-zod) - [Mocking](#mocking) - [Powered by Zod](#powered-by-zod) - [Utilities for Zod](#utilities-for-zod) - [Installation](#installation) - [Requirements](#requirements) - [From `npm`](#from-npm) - [Basic usage](#basic-usage) - [Primitives](#primitives) - [Coercion for primitives](#coercion-for-primitives) - [Literals](#literals) - [Strings](#strings) - [Datetimes](#datetimes) - [Dates](#dates) - [Times](#times) - [IP addresses](#ip-addresses) - [IP ranges](#ip-ranges-cidr) - [Numbers](#numbers) - [BigInts](#bigints) - [NaNs](#nans) - [Booleans](#booleans) - [Dates](#dates-1) - [Zod enums](#zod-enums) - [Native enums](#native-enums) - [Optionals](#optionals) - [Nullables](#nullables) - [Objects](#objects) - [`.shape`](#shape) - [`.keyof`](#keyof) - [`.extend`](#extend) - [`.merge`](#merge) - [`.pick/.omit`](#pickomit) - [`.partial`](#partial) - [`.deepPartial`](#deeppartial) - [`.required`](#required) - [`.passthrough`](#passthrough) - [`.strict`](#strict) - [`.strip`](#strip) - [`.catchall`](#catchall) - [Arrays](#arrays) - [`.element`](#element) - [`.nonempty`](#nonempty) - [`.min/.max/.length`](#minmaxlength) - [Tuples](#tuples) - [Unions](#unions) - [Discriminated unions](#discriminated-unions) - [Records](#records) - [Record key type](#record-key-type) - [Maps](#maps) - [Sets](#sets) - [Intersections](#intersections) - [Recursive types](#recursive-types) - [ZodType with ZodEffects](#zodtype-with-zodeffects) - [JSON type](#json-type) - [Cyclical objects](#cyclical-objects) - [Promises](#promises) - [Instanceof](#instanceof) - [Functions](#functions) - [Preprocess](#preprocess) - [Custom schemas](#custom-schemas) - [Schema methods](#schema-methods) - [`.parse`](#parse) - [`.parseAsync`](#parseasync) - [`.safeParse`](#safeparse) - [`.safeParseAsync`](#safeparseasync) - [`.refine`](#refine) - [Arguments](#arguments) - [Customize error path](#customize-error-path) - [Asynchronous refinements](#asynchronous-refinements) - [Relationship to transforms](#relationship-to-transforms) - [`.superRefine`](#superrefine) - [Abort early](#abort-early) - [Type refinements](#type-refinements) - [`.transform`](#transform) - [Chaining order](#chaining-order) - [Validating during transform](#validating-during-transform) - [Relationship to refinements](#relationship-to-refinements) - [Async transforms](#async-transforms) - [`.default`](#default) - [`.describe`](#describe) - [`.catch`](#catch) - [`.optional`](#optional) - [`.nullable`](#nullable) - [`.nullish`](#nullish) - [`.array`](#array) - [`.promise`](#promise) - [`.or`](#or) - [`.and`](#and) - [`.brand`](#brand) - [`.readonly`](#readonly) - [`.pipe`](#pipe) - [You can use `.pipe()` to fix common issues with `z.coerce`.](#you-can-use-pipe-to-fix-common-issues-with-zcoerce) - [Guides and concepts](#guides-and-concepts) - [Type inference](#type-inference) - [Writing generic functions](#writing-generic-functions) - [Constraining allowable inputs](#constraining-allowable-inputs) - [Error handling](#error-handling) - [Error formatting](#error-formatting) - [Comparison](#comparison) - [Joi](#joi) - [Yup](#yup) - [io-ts](#io-ts) - [Runtypes](#runtypes) - [Ow](#ow) - [Changelog](#changelog) <br/> ## Introduction Zod is a TypeScript-first schema declaration and validation library. I'm using the term "schema" to broadly refer to any data type, from a simple `string` to a complex nested object. Zod is designed to be as developer-friendly as possible. The goal is to eliminate duplicative type declarations. With Zod, you declare a validator _once_ and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures. Some other great aspects: - Zero dependencies - Works in Node.js and all modern browsers - Tiny: 8kb minified + zipped - Immutable: methods (e.g. `.optional()`) return a new instance - Concise, chainable interface - Functional approach: [parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) - Works with plain JavaScript too! You don't need to use TypeScript. <br/> ## Sponsors Sponsorship at any level is appreciated and encouraged. If you built a paid product using Zod, consider one of the [corporate tiers](https://github.com/sponsors/colinhacks). <br/> <h3 align="center">Platinum</h3> <table align="center" style="justify-content: center;align-items: center;display: flex;"> <tr> <td align="center"> <p></p> <p> <a href="https://www.coderabbit.ai/"> <picture height="80px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/eea24edb-ff20-4532-b57c-e8719f455d6d"> <img alt="CodeRabbit logo" height="80px" src="https://github.com/user-attachments/assets/d791bc7d-dc60-4d55-9c31-97779839cb74"> </picture> </a> <br /> Cut code review time & bugs in half <br/> <a href="https://www.coderabbit.ai/" style="text-decoration:none;">coderabbit.ai</a> </p> <p></p> </td> </tr> </table> <br/> <h3 align="center">Gold</h3> <table align="center" style="justify-content: center;align-items: center;display: flex;"> <tr> <td align="center"> <p></p> <p> <a href="https://www.courier.com/?utm_source=zod&utm_campaign=osssponsors"> <picture height="62px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/6b09506a-78de-47e8-a8c1-792efe31910a"> <img alt="Courier logo" height="62px" src="https://github.com/user-attachments/assets/6b09506a-78de-47e8-a8c1-792efe31910a"> </picture> </a> <br /> The API platform for sending notifications <br/> <a href="https://www.courier.com/?utm_source=zod&utm_campaign=osssponsors" style="text-decoration:none;">courier.com</a> </p> <p></p> </td> <td align="center"> <p></p> <p> <a href="https://liblab.com/?utm_source=zod"> <picture height="62px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/34dfa1a2-ce94-46f4-8902-fbfac3e1a9bc"> <img alt="LibLab" height="62px" src="https://github.com/user-attachments/assets/3de0b617-5137-49c4-b72d-a033cbe602d8"> </picture> </a> <br /> Generate better SDKs for your APIs <br/> <a href="https://liblab.com/?utm_source=zod" style="text-decoration:none;">liblab.com</a> </p> <p></p> </td> </tr> <tr> <td align="center"> <p></p> <p> <a href="https://neon.tech"> <picture height="68px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/83b4b1b1-a9ab-4ae5-a632-56d282f0c444"> <img alt="Neon" height="68px" src="https://github.com/user-attachments/assets/b5799fc8-81ff-4053-a1c3-b29adf85e7a1"> </picture> </a> <br /> Serverless Postgres — Ship faster <br/> <a href="https://neon.tech" style="text-decoration:none;">neon.tech</a> </p> <p></p> </td> <td align="center"> <p></p> <p> <a href="https://retool.com/?utm_source=github&utm_medium=referral&utm_campaign=zod"> <picture height="45px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/colinhacks/zod/assets/3084745/ac65013f-aeb4-48dd-a2ee-41040b69cbe6"> <img alt="Retool" height="45px" src="https://github.com/colinhacks/zod/assets/3084745/5ef4c11b-efeb-4495-90a8-41b83f798600"> </picture> </a> <br /> Build AI apps and workflows with <a href="https://retool.com/products/ai?utm_source=github&utm_medium=referral&utm_campaign=zod">Retool AI</a> <br/> <a href="https://retool.com/?utm_source=github&utm_medium=referral&utm_campaign=zod" style="text-decoration:none;">retool.com</a> </p> <p></p> </td> </tr> <tr> <td align="center"> <p></p> <p> <a href="https://stainless.com"> <picture height="45px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/colinhacks/zod/assets/3084745/f20759c1-3e51-49d0-a31e-bbc43abec665"> <img alt="stainless" height="45px" src="https://github.com/colinhacks/zod/assets/3084745/e9444e44-d991-4bba-a697-dbcfad608e47"> </picture> </a> <br /> Generate best-in-class SDKs <br/> <a href="https://stainless.com" style="text-decoration:none;">stainless.com</a> </p> <p></p> </td> <td align="center"> <p></p> <p> <a href="https://speakeasy.com/?utm_source=zod+docs"> <picture height="40px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/colinhacks/zod/assets/3084745/b1d86601-c7fb-483c-9927-5dc24ce8b737"> <img alt="speakeasy" height="40px" src="https://github.com/colinhacks/zod/assets/3084745/647524a4-22bb-4199-be70-404207a5a2b5"> </picture> </a> <br /> SDKs & Terraform providers for your API <br/> <a href="https://speakeasy.com/?utm_source=zod+docs" style="text-decoration:none;">speakeasy.com</a> </p> <p></p> </td> </tr> </table> <br/> <h3 align="center">Silver</h3> <table align="center" style="justify-content: center;align-items: center;display: flex;"> <tr> <td align="center"> <img src="https://avatars.githubusercontent.com/u/72055470?s=200&v=4" height="50px;" alt="Nitric" /> <br /> <a style="text-decoration:none;" href="https://nitric.io/" target="_blank">Nitric</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/89474619?s=200&v=4" height="50px;" alt="PropelAuth" /> <br /> <a style="text-decoration:none;" href="https://www.propelauth.com/" target="_blank">PropelAuth</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/80861386?s=200&v=4" height="50px;" alt="Cerbos" /> <br /> <a style="text-decoration:none;" href="https://cerbos.dev/" target="_blank">Cerbos</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/301879?s=200&v=4" height="50px;" alt="Scalar.com logo" /> <br /> <a style="text-decoration:none;" href="https://scalar.com/" target="_blank">Scalar</a> </td> </tr><tr> <td align="center"> <img src="https://avatars.githubusercontent.com/u/95297378?s=200&v=4" height="50px;" alt="Trigger.dev logo" /> <br /> <a style="text-decoration:none;" href="https://trigger.dev" target="_blank">Trigger.dev</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/125754?s=200&v=4" height="50px;" alt="Transloadit logo" /> <br /> <a style="text-decoration:none;" href="https://transloadit.com/?utm_source=zod&utm_medium=refe rral&utm_campaign=sponsorship&utm_content=github" target="_blank">Transloadit</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/107880645?s=200&v=4" height="50px;" alt="Infisical logo" /> <br /> <a style="text-decoration:none;" href="https://infisical.com" target="_blank">Infisical</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/91036480?s=200&v=4" height="50px;" alt="Whop logo" /> <br /> <a style="text-decoration:none;" href="https://whop.com/" target="_blank">Whop</a> </td> </tr><tr> <td align="center"> <img src="https://avatars.githubusercontent.com/u/36402888?s=200&v=4" height="50px;" alt="CryptoJobsList logo" /> <br /> <a style="text-decoration:none;" href="https://cryptojobslist.com/" target="_blank">CryptoJobsList</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/70170949?s=200&v=4" height="50px;" alt="Plain logo" /> <br /> <a style="text-decoration:none;" href="https://plain.com/" target="_blank">Plain.</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/78935958?s=200&v=4" height="50px;" alt="Inngest logo" /> <br /> <a style="text-decoration:none;" href="https://inngest.com/" target="_blank">Inngest</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/13880908?s=200&v=4" height="50px;" alt="Storyblok CMS" /> <br /> <a style="text-decoration:none;" href="https://storyblok.com/" target="_blank">Storyblok</a> </td> </tr><tr> <td align="center"> <img src="https://avatars.githubusercontent.com/u/16199997?s=200&v=4" height="50px;" alt="Mux logo" /> <br /> <a style="text-decoration:none;" href="https://mux.link/zod" target="_blank">Mux</a> </td> <td align="center"> <img src="https://avatars.githubusercontent.com/u/76428554?s=200&v=4" height="50px;" alt="Cybozu logo" /> <br /> <a style="text-decoration:none;" href="https://cybozu.co.jp/index.html" target="_blank">Cybozu</a> </td> </tr> </table> <br/> <h3 align="center">Bronze</h3> <table align="center" style="justify-content: center;align-items: center;display: flex;"> <tr> <td align="center"> <a href="https://www.val.town/"> <picture width="100%" height="40px"> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/36961d2e-d92e-42af-9031-a41885ece5f4"> <img alt="val town logo" src="https://github.com/user-attachments/assets/95305fc4-4da6-4bf8-aea4-bae8f5893e5d" height="40px"> </picture> </a> </td> <td align="center"> <a href="https://www.route4me.com/"> <img src="https://avatars.githubusercontent.com/u/7936820?s=200&v=4" height="40px;" alt="route4me logo" /> </a> </td> <td align="center"> <a href="https://encore.dev"> <img src="https://github.com/colinhacks/zod/assets/3084745/5ad94e73-cd34-4957-9979-37da85fcf9cd" height="40px;" alt="Encore.dev logo" /> </a> </td> <td align="center"> <a href="https://www.replay.io/"> <img src="https://avatars.githubusercontent.com/u/60818315?s=200&v=4" height="40px;" alt="Replay.io logo" /> </a> </td> </tr> <tr> <td align="center"> <a href="https://www.numeric.io"> <img src="https://i.imgur.com/kTiLtZt.png" height="40px;" alt="Numeric logo" /> </a> </td> <td align="center"> <a href="https://marcatopartners.com"> <img src="https://avatars.githubusercontent.com/u/84106192?s=200&v=4" height="40px;" alt="Marcato Partners" /> </a> </td> <td align="center"> <a href="https://interval.com"> <img src="https://avatars.githubusercontent.com/u/67802063?s=200&v=4" height="40px;" alt="" /> </a> </td> <td align="center"> <a href="https://seasoned.cc"> <img src="https://avatars.githubusercontent.com/u/33913103?s=200&v=4" height="40px;" alt="" /> </a> </td> </tr> <tr> <td align="center"> <a href="https://www.bamboocreative.nz/"> <img src="https://avatars.githubusercontent.com/u/41406870?v=4" height="40px;" alt="Bamboo Creative logo" /> </a> </td> <td align="center"> <a href="https://github.com/jasonLaster"> <img src="https://avatars.githubusercontent.com/u/254562?v=4" height="40px;" alt="Jason Laster" /> </a> </td> </tr> </table> <!-- <h3 align="center">Bronze</h3> <table align="center" style="justify-content: center;align-items: center;display: flex;"> <tr> <td>Brandon Bayer</td> <td>Jiří Brabec</td> <td>Alex Johansson</td> <td>Fungible Systems</td> </tr> <tr> <td>Adaptable</td> <td>Avana Wallet</td> <td>Jason Lengstorf</td> <td>Global Illumination, Inc.</td> </tr> <tr> <td>MasterBorn</td> <td>Ryan Palmer</td> <td>Michael Sweeney</td> <td>Nextbase</td> </tr> <tr> <td>Remotion</td> <td>Connor Sinnott</td> <td>Mohammad-Ali A'râbi</td> <td>Supatool</td> </tr> </table> --> ### Ecosystem There are a growing number of tools that are built atop or support Zod natively! If you've built a tool or library on top of Zod, tell me about it [on Twitter](https://twitter.com/colinhacks) or [start a Discussion](https://github.com/colinhacks/zod/discussions). I'll add it below and tweet it out. #### Resources - [Total TypeScript Zod Tutorial](https://www.totaltypescript.com/tutorials/zod) by [@mattpocockuk](https://twitter.com/mattpocockuk) - [Fixing TypeScript's Blindspot: Runtime Typechecking](https://www.youtube.com/watch?v=rY_XqfSHock) by [@jherr](https://twitter.com/jherr) #### API libraries - [`tRPC`](https://github.com/trpc/trpc): Build end-to-end typesafe APIs without GraphQL. - [`@anatine/zod-nestjs`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-nestjs): Helper methods for using Zod in a NestJS project. - [`zod-endpoints`](https://github.com/flock-community/zod-endpoints): Contract-first strictly typed endpoints with Zod. OpenAPI compatible. - [`zhttp`](https://github.com/evertdespiegeleer/zhttp): An OpenAPI compatible, strictly typed http library with Zod input and response validation. - [`domain-functions`](https://github.com/SeasonedSoftware/domain-functions/): Decouple your business logic from your framework using composable functions. With first-class type inference from end to end powered by Zod schemas. - [`@zodios/core`](https://github.com/ecyrbe/zodios): A typescript API client with runtime and compile time validation backed by axios and zod. - [`express-zod-api`](https://github.com/RobinTail/express-zod-api): Build Express-based APIs with I/O schema validation and custom middlewares. - [`tapiduck`](https://github.com/sumukhbarve/monoduck/blob/main/src/tapiduck/README.md): End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler. - [`koa-zod-router`](https://github.com/JakeFenley/koa-zod-router): Create typesafe routes in Koa with I/O validation using Zod. - [`zod-sockets`](https://github.com/RobinTail/zod-sockets): Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs - [`oas-tszod-gen`](https://github.com/inkognitro/oas-tszod-gen): Client SDK code generator to convert OpenApi v3 specifications into TS endpoint caller functions with Zod types. - [`GQLoom`](https://github.com/modevol-com/gqloom): Weave GraphQL schema and resolvers using Zod. - [`oRPC`](https://github.com/unnoq/orpc): Typesafe APIs Made Simple #### Form integrations - [`react-hook-form`](https://github.com/react-hook-form/resolvers#zod): A first-party Zod resolver for React Hook Form. - [`TanStack Form`](https://github.com/TanStack/form): Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit - [`zod-validation-error`](https://github.com/causaly/zod-validation-error): Generate user-friendly error messages from `ZodError`s. - [`zod-formik-adapter`](https://github.com/robertLichtnow/zod-formik-adapter): A community-maintained Formik adapter for Zod. - [`react-zorm`](https://github.com/esamattis/react-zorm): Standalone `<form>` generation and validation for React using Zod. - [`zodix`](https://github.com/rileytomasek/zodix): Zod utilities for FormData and URLSearchParams in Remix loaders and actions. - [`conform`](https://conform.guide/api/zod/parseWithZod): A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js. - [`remix-params-helper`](https://github.com/kiliman/remix-params-helper): Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps. - [`formik-validator-zod`](https://github.com/glazy/formik-validator-zod): Formik-compliant validator library that simplifies using Zod with Formik. - [`zod-i18n-map`](https://github.com/aiji42/zod-i18n): Useful for translating Zod error messages. - [`@modular-forms/solid`](https://github.com/fabian-hiller/modular-forms): Modular form library for SolidJS that supports Zod for validation. - [`houseform`](https://github.com/crutchcorn/houseform/): A React form library that uses Zod for validation. - [`sveltekit-superforms`](https://github.com/ciscoheat/sveltekit-superforms): Supercharged form library for SvelteKit with Zod validation. - [`mobx-zod-form`](https://github.com/MonoidDev/mobx-zod-form): Data-first form builder based on MobX & Zod. - [`@vee-validate/zod`](https://github.com/logaretm/vee-validate/tree/main/packages/zod): Form library for Vue.js with Zod schema validation. - [`zod-form-renderer`](https://github.com/thepeaklab/zod-form-renderer): Auto-infer form fields from zod schema and render them with react-hook-form with E2E type safety. - [`antd-zod`](https://github.com/MrBr/antd-zod): Zod adapter for Ant Design form fields validation. - [`frrm`](https://github.com/schalkventer/frrm): Tiny 0.5kb Zod-based, HTML form abstraction that goes brr. #### Zod to X - [`zod-to-ts`](https://github.com/sachinraja/zod-to-ts): Generate TypeScript definitions from Zod schemas. - [`zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema): Convert your Zod schemas into [JSON Schemas](https://json-schema.org/). - [`@anatine/zod-openapi`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi): Converts a Zod schema to an OpenAPI v3.x `SchemaObject`. - [`zod-fast-check`](https://github.com/DavidTimms/zod-fast-check): Generate `fast-check` arbitraries from Zod schemas. - [`zod-dto`](https://github.com/kbkk/abitia/tree/master/packages/zod-dto): Generate Nest.js DTOs from a Zod schema. - [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas. - [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters. - [`nestjs-graphql-zod`](https://github.com/incetarik/nestjs-graphql-zod): Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas. - [`zod-openapi`](https://github.com/samchungy/zod-openapi): Create full OpenAPI v3.x documentation from Zod schemas. - [`fastify-zod-openapi`](https://github.com/samchungy/fastify-zod-openapi): Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas. - [`typeschema`](https://typeschema.com/): Universal adapter for schema validation. - [`zodex`](https://github.com/commonbaseapp/zodex): (De)serialization for zod schemas #### X to Zod - [`ts-to-zod`](https://github.com/fabien0102/ts-to-zod): Convert TypeScript definitions into Zod schemas. - [`@runtyping/zod`](https://github.com/johngeorgewright/runtyping): Generate Zod from static types & JSON schema. - [`json-schema-to-zod`](https://github.com/StefanTerdell/json-schema-to-zod): Convert your [JSON Schemas](https://json-schema.org/) into Zod schemas. [Live demo](https://StefanTerdell.github.io/json-schema-to-zod-react/). - [`json-to-zod`](https://github.com/rsinohara/json-to-zod): Convert JSON objects into Zod schemas. [Live demo](https://rsinohara.github.io/json-to-zod-react/). - [`graphql-codegen-typescript-validation-schema`](https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema): GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema. - [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema. - [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs. - [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema. - [`drizzle-zod`](https://orm.drizzle.team/docs/zod): Emit Zod schemas from your Drizzle schema. - [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod. - [`zod-prisma-types`](https://github.com/chrishoermann/zod-prisma-types) Create Zod types from your Prisma models. - [`quicktype`](https://app.quicktype.io/): Convert JSON objects and JSON schemas into Zod schemas. - [`@sanity-typed/zod`](https://github.com/saiichihashimoto/sanity-typed/tree/main/packages/zod): Generate Zod Schemas from [Sanity Schemas](https://www.sanity.io/docs/schema-types). - [`java-to-zod`](https://github.com/ivangreene/java-to-zod): Convert POJOs to Zod schemas - [`Orval`](https://github.com/anymaniax/orval): Generate Zod schemas from OpenAPI schemas - [`Kubb`](https://github.com/kubb-labs/kubb): Generate SDKs and Zod schemas from your OpenAPI schemas #### Mocking - [`@anatine/zod-mock`](https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock): Generate mock data from a Zod schema. Powered by [faker.js](https://github.com/faker-js/faker). - [`zod-mocking`](https://github.com/dipasqualew/zod-mocking): Generate mock data from your Zod schemas. - [`zod-fixture`](https://github.com/timdeschryver/zod-fixture): Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way. - [`zocker`](https://zocker.sigrist.dev): Generate plausible mock-data from your schemas. - [`zodock`](https://github.com/ItMaga/zodock) Generate mock data based on Zod schemas. - [`zod-schema-faker`](https://github.com/soc221b/zod-schema-faker) Generates mock data from Zod schemas. Powered by [@faker-js/faker](https://github.com/faker-js/faker) and [randexp.js](https://github.com/fent/randexp.js) #### Powered by Zod - [`freerstore`](https://github.com/JacobWeisenburger/freerstore): Firestore cost optimizer. - [`slonik`](https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference): Node.js Postgres client with strong Zod integration. - [`schemql`](https://github.com/a2lix/schemql): Enhances your SQL workflow by combining raw SQL with targeted type safety and schema validation. - [`soly`](https://github.com/mdbetancourt/soly): Create CLI applications with zod. - [`pastel`](https://github.com/vadimdemedes/pastel): Create CLI applications with react, zod, and ink. - [`zod-xlsx`](https://github.com/sidwebworks/zod-xlsx): A xlsx based resource validator using Zod schemas. - [`znv`](https://github.com/lostfictions/znv): Type-safe environment parsing and validation for Node.js with Zod schemas. - [`zod-config`](https://github.com/alexmarqs/zod-config): Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod. - [`unplugin-environment`](https://github.com/r17x/js/tree/main/packages/unplugin-environment#readme): A plugin for loading enviroment variables safely with schema validation, simple with virtual module, type-safe with intellisense, and better DX 🔥 🚀 👷. Powered by Zod. - [`zod-struct`](https://codeberg.org/reesericci/zod-struct): Create runtime-checked structs with Zod. - [`zod-csv`](https://github.com/bartoszgolebiowski/zod-csv): Validation helpers for zod for parsing CSV data. - [`fullproduct.dev`](https://fullproduct.dev?identity=freelancers&v=z3): Universal Expo + Next.js App Starter that uses Zod schemas as the single source of truth to keep generated MDX docs, GraphQL, database models, forms, and fetcher functions in sync. #### Utilities for Zod - [`zod_utilz`](https://github.com/JacobWeisenburger/zod_utilz): Framework agnostic utilities for Zod. - [`zod-playground`](https://github.com/marilari88/zod-playground): A tool for learning and testing Zod schema validation functionalities. [Link](https://zod-playground.vercel.app/). - [`zod-sandbox`](https://github.com/nereumelo/zod-sandbox): Controlled environment for testing zod schemas. [Live demo](https://zod-sandbox.vercel.app/). - [`zod-dev`](https://github.com/schalkventer/zod-dev): Conditionally disables Zod runtime parsing in production. - [`zod-accelerator`](https://github.com/duplojs/duplojs-zod-accelerator): Accelerates Zod's throughput up to ~100x. <br/> ## Installation ### Requirements - TypeScript 4.5+! - You must enable `strict` mode in your `tsconfig.json`. This is a best practice for all TypeScript projects. ```ts // tsconfig.json { // ... "compilerOptions": { // ... "strict": true } } ``` ### From `npm` ```sh npm install zod # npm deno add npm:zod # deno yarn add zod # yarn bun add zod # bun pnpm add zod # pnpm ``` Zod also publishes a canary version on every commit. To install the canary: ```sh npm install zod@canary # npm deno add npm:zod@canary # deno yarn add zod@canary # yarn bun add zod@canary # bun pnpm add zod@canary # pnpm ``` > The rest of this README assumes you are using npm and importing directly from the `"zod"` package. <br/> ## Basic usage Creating a simple string schema ```ts 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 } ``` Creating an object schema ```ts 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 } ``` <br/> ## Primitives ```ts 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(); ``` <br/> ## Coercion for primitives Zod now provides a more convenient way to coerce primitive values. ```ts const schema = z.coerce.string(); schema.parse("tuna"); // => "tuna" schema.parse(12); // => "12" ``` During the parsing step, the input is passed through the `String()` function, which is a JavaScript built-in for coercing data into strings. ```ts schema.parse(12); // => "12" schema.parse(true); // => "true" schema.parse(undefined); // => "undefined" schema.parse(null); // => "null" ``` The returned schema is a normal `ZodString` instance so you can use all string methods. ```ts z.coerce.string().email().min(5); ``` **How coercion works** All primitive types support coercion. Zod coerces all inputs using the built-in constructors: `String(input)`, `Number(input)`, `new Date(input)`, etc. ```ts 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) ``` **Note** — Boolean coercion with `z.coerce.boolean()` may not work how you expect. Any [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) value is coerced to `true`, and any [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) value is coerced to `false`. ```ts 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 ``` For more control over coercion logic, consider using [`z.preprocess`](#preprocess) or [`z.pipe()`](#pipe). <br/> ## Literals Literal schemas represent a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types), like `"hello world"` or `5`. ```ts 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" ``` > Currently there is no support for Date literals in Zod. If you have a use case for this feature, please file an issue. <br/> ## Strings Zod includes a handful of string-specific validations. ```ts // 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 z.string().cidr(); // 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] or HH:mm) z.string().duration(); // ISO 8601 duration z.string().base64(); ``` > Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions that can be used in conjunction with [Refinements](#refine). You can customize some common error messages when creating a string schema. ```ts const name = z.string({ required_error: "Name is required", invalid_type_error: "Name must be a string", }); ``` When using validation methods, you can pass in an additional argument to provide a custom error message. ```ts 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" }); z.string().cidr({ message: "Invalid CIDR" }); ``` ### Datetimes As you may have noticed, Zod string includes a few date/time related validations. These validations are regular expression based, so they are not as strict as a full date/time library. However, they are very convenient for validating user input. The `z.string().datetime()` method enforces ISO 8601; default is no timezone offsets and arbitrary sub-second decimal precision. Seconds may be omitted if precision is not set. ```ts 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:00Z"); // pass (hours and minutes only) 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`. ```ts const datetime = z.string().datetime({ offset: true }); datetime.parse("2020-01-01T00:00:00+02:00"); // pass datetime.parse("2020-01-01T00: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) ``` Allow unqualified (timezone-less) datetimes with the `local` flag. ```ts const schema = z.string().datetime({ local: true }); schema.parse("2020-01-01T00:00:00"); // pass schema.parse("2020-01-01T00:00"); // pass ``` You can additionally constrain the allowable `precision`. By default, arbitrary sub-second precision is supported (but optional). ```ts 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:00Z"); // fail datetime.parse("2020-01-01T00:00:00.123456Z"); // fail ``` ### Dates > Added in Zod 3.23 The `z.string().date()` method validates strings in the format `YYYY-MM-DD`. ```ts const date = z.string().date(); date.parse("2020-01-01"); // pass date.parse("2020-1-1"); // fail date.parse("2020-01-32"); // fail ``` ### Times > Added in Zod 3.23 The `z.string().time()` method validates strings in the format `HH:MM` or `HH:MM:SS[.s+]`. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind. ```ts const time = z.string().time(); time.parse("00:00:00"); // pass time.parse("09:52:31"); // pass time.parse("09:52"); // 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) ``` You can set the `precision` option to constrain the allowable decimal precision. ```ts 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 time.parse("00:00"); // fail ``` ### IP addresses By default `.ip()` allows both IPv4 and IPv6. ```ts 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 ``` You can additionally set the IP `version`. ```ts 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 ``` ### IP ranges (CIDR) Validate IP address ranges specified with [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). By default, `.cidr()` allows both IPv4 and IPv6. ```ts const cidr = z.string().cidr(); cidr.parse("192.168.0.0/24"); // pass cidr.parse("2001:db8::/32"); // pass ``` You can specify a version with the `version` parameter. ```ts const ipv4Cidr = z.string().cidr({ version: "v4" }); ipv4Cidr.parse("84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"); // fail const ipv6Cidr = z.string().cidr({ version: "v6" }); ipv6Cidr.parse("192.168.1.1"); // fail ``` <br/> ## Numbers You can customize certain error messages when creating a number schema. ```ts const age = z.number({ required_error: "Age is required", invalid_type_error: "Age must be a number", }); ``` Zod includes a handful of number-specific validations. ```ts 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 ``` Optionally, you can pass in a second argument to provide a custom error message. ```ts z.number().lte(5, { message: "this👏is👏too👏big" }); ``` <br/> ## BigInts Zod includes a handful of bigint-specific validations. ```ts 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. ``` <br/> ## NaNs You can customize certain error messages when creating a nan schema. ```ts const isNaN = z.nan({ required_error: "isNaN is required", invalid_type_error: "isNaN must be 'not a number'", }); ``` <br/> ## Booleans You can customize certain error messages when creating a boolean schema. ```ts const isActive = z.boolean({ required_error: "isActive is required", invalid_type_error: "isActive must be a boolean", }); ``` <br/> ## Dates Use z.date() to validate `Date` instances. ```ts z.date().safeParse(new Date()); // success: true z.date().safeParse("2022-01-12T00:00:00.000Z"); // success: false ``` You can customize certain error messages when creating a date schema. ```ts const myDateSchema = z.date({ required_error: "Please select a date and time", invalid_type_error: "That's not a date!", }); ``` Zod provides a handful of date-specific validations. ```ts z.date().min(new Date("1900-01-01"), { message: "Too old" }); z.date().max(new Date(), { message: "Too young!" }); ``` **Coercion to Date** Since [zod 3.20](https://github.com/colinhacks/zod/releases/tag/v3.20), use [`z.coerce.date()`](#coercion-for-primitives) to pass the input through `new Date(input)`. ```ts 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 ``` For older zod versions, use [`z.preprocess`](#preprocess) like [described in this thread](https://github.com/colinhacks/zod/discussions/879#discussioncomment-2036276). <br/> ## Zod enums ```ts const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]); type FishEnum = z.infer<typeof FishEnum>; // 'Salmon' | 'Tuna' | 'Trout' ``` `z.enum` is a Zod-native way to declare a schema with a fixed set of allowable _string_ values. Pass the array of values directly into `z.enum()`. Alternatively, use `as const` to define your enum values as a tuple of strings. See the [const assertion docs](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) for details. ```ts const VALUES = ["Salmon", "Tuna", "Trout"] as const; const FishEnum = z.enum(VALUES); ``` This is not allowed, since Zod isn't able to infer the exact values of each element. ```ts const fish = ["Salmon", "Tuna", "Trout"]; const FishEnum = z.enum(fish); ``` **`.enum`** To get autocompletion with a Zod enum, use the `.enum` property of your schema: ```ts FishEnum.enum.Salmon; // => autocompletes FishEnum.enum; /* => { Salmon: "Salmon", Tuna: "Tuna", Trout: "Trout", } */ ``` You can also retrieve the list of options as a tuple with the `.options` property: ```ts FishEnum.options; // ["Salmon", "Tuna", "Trout"]; ``` **`.exclude/.extract()`** You can create subsets of a Zod enum with the `.exclude` and `.extract` methods. ```ts const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]); const SalmonAndTrout = FishEnum.extract(["Salmon", "Trout"]); const TunaOnly = FishEnum.exclude(["Salmon", "Trout"]); ``` <br/> ## Native enums Zod enums are the recommended approach to defining and validating enums. But if you need to validate against an enum from a third-party library (or you don't want to rewrite your existing enums) you can use `z.nativeEnum()`. **Numeric enums** ```ts 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 ``` **String enums** ```ts 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** The `.nativeEnum()` function works for `as const` objects as well. ⚠️ `as const` requires TypeScript 3.4+! ```ts 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: ```ts FruitEnum.enum.Apple; // "apple" ``` <br/> ## Optionals You can make any schema optional with `z.optional()`. This wraps the schema in a `ZodOptional` instance and returns the result. ```ts const schema = z.optional(z.string()); schema.parse(undefined); // => returns undefined type A = z.infer<typeof schema>; // string | undefined ``` For convenience, you can also call the `.optional()` method on an existing schema. ```ts const user = z.object({ username: z.string().optional(), }); type C = z.infer<typeof user>; // { username?: string | undefined }; ``` You can extract the wrapped schema from a `ZodOptional` instance with `.unwrap()`. ```ts const stringSchema = z.string(); const optionalString = stringSchema.optional(); optionalString.unwrap() === stringSchema; // true ``` <br/> ## Nullables Similarly, you can create nullable types with `z.nullable()`. ```ts const nullableString = z.nullable(z.string()); nullableString.parse("asdf"); // => "asdf" nullableString.parse(null); // => null ``` Or use the `.nullable()` method. ```ts const E = z.string().nullable(); // equivalent to nullableString type E = z.infer<typeof E>; // string | null ``` Extract the inner schema with `.unwrap()`. ```ts const stringSchema = z.string(); const nullableString = stringSchema.nullable(); nullableString.unwrap() === stringSchema; // true ``` <br/> ## Objects ```ts // 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: numb