Typescript type validator that is really fancy and gives the same typing messages at coding-time
None
2023-01-01
<div><div><header><p></p><h2>Isomorphic type syntax for TS/JS</h2><p></p></header><main><div><div><h3>Isomorphic</h3><p>Define types using TS syntax. Infer them 1:1. Use them to validate your data at runtime.</p></div><div><h3>Native JS/TS</h3><p>No extensions, plugins or compilers required</p></div><div><h3>Concise</h3><p>Say more with less</p></div><div><h3>Powerful</h3><p>As a full type system, ArkType understands your data in ways other validators never could</p></div><div><h3>Fast</h3><p>Types are optimized for traversal and can validate your data 2-10x faster than existing validators (details to come)</p></div><div><h3>Portable</h3><p>Most ArkType definitions are just strings and objects. Serialize them and take them anywhere your data can go!</p></div></div></main></div>||||I|||| Skip to main content
 Tutorial
 0.1.2
 * Next
 * 0.1.2
 * 0.1.1
 * 0.1.0

 ArkType

 Isomorphic type syntax for TS/JS

 Isomorphic

 Define types using TS syntax. Infer them 1:1. Use them to validate your data at runtime.

 Native JS/TS

 No extensions, plugins or compilers required

 Concise

 Say more with less

 Powerful

 As a full type system, ArkType understands your data in ways other validators never could

 Fast

 Types are optimized for traversal and can validate your data 2-10x faster than existing validators (details to come)

 Portable

 Most ArkType definitions are just strings and objects. Serialize them and take them anywhere your data can go!

 Try it here!
 Docs
 * Tutorial
 Community
 * GitHub
 * Discord
 Copyright © 2023 Arktype, Inc. Built with Docusaurus.
ArkType | ArkType
https://arktype.io/
Arktypeio
2023-02-23
<div><div>
 <article><h2>ArkType <sub><sup>Isomorphic types for TS/JS</sup></sub></h2>
<p><a href="/arktypeio/arktype/blob/main/dev/arktype.io/static/img/arktype.gif"></a>
<sub><i><code>typescript@4.9.5</code> in VS Code— no extensions or plugins required (<a href="#how">how?</a>)</i></sub></p>
<h2>Install <sub><sub>📦<code>4KB</code> gzipped, <code>0</code> dependencies</sub></sub></h2>
<p><a href="/arktypeio/arktype/blob/main/dev/arktype.io/static/img/npm.svg"></a> <code>npm install arktype</code> <sub>(or whatever package manager you prefer)</sub></p>
<p><a href="/arktypeio/arktype/blob/main/dev/arktype.io/static/img/deno.svg"></a> <code>import { type } from "https://deno.land/x/arktype"</code></p>
<p><a href="/arktypeio/arktype/blob/main/dev/arktype.io/static/img/logo.svg"></a> <i>Try it in-browser at <a href="https://arktype.io/try">arktype.io/try</a></i> <sub>(the types aren't quite as snappy as they will be in
your IDE)</sub></p>
<p>Our types are tested in <a href="https://www.typescriptlang.org/tsconfig#strict">strict-mode</a> with TypeScript versions <code>4.8</code>, <code>4.9</code>, and <code>5.0</code>.</p>
<p><em>Our APIs have mostly stabilized, but details may still change during the alpha/beta stages of our 1.0 release. If you have suggestions that may require a breaking change, now is the time to let us know!</em> ⛵</p>
<h2>Types</h2>
<p><a href="https://arktype.io/docs/#your-first-type">Try it in-browser.</a></p>
<div><pre>import { type } from "arktype"
// Define a type...
export const user = type({
 name: "string",
 device: {
 platform: "'android'|'ios'",
 "version?": "number"
 }
})
// Infer it...
export type User = typeof user.infer
// Validate your data anytime, anywhere, with the same clarity and precision you expect from TypeScript.
export const { data, problems } = user({
 name: "Alan Turing",
 device: {
 platform: "enigma"
 }
})
if (problems) {
 // "device/platform must be 'android' or 'ios' (was 'enigma')"
 console.log(problems.summary)
}</pre></div>
<h3>Scopes</h3>
<p><a href="https://arktype.io/docs/scopes">Try it in-browser.</a></p>
<div><pre>import { scope } from "arktype"
// Scopes are collections of types that can reference each other.
export const types = scope({
 package: {
 name: "string",
 "dependencies?": "package[]",
 "contributors?": "contributor[]"
 },
 contributor: {
 // Subtypes like 'email' are inferred like 'string' but provide additional validation at runtime.
 email: "email",
 "packages?": "package[]"
 }
}).compile()
// Cyclic types are inferred to arbitrary depth...
export type Package = typeof types.package.infer
// And can validate cyclic data.
const packageData: Package = {
 name: "arktype",
 dependencies: [{ name: "typescript" }],
 contributors: [{ email: "david@sharktypeio" }]
}
packageData.dependencies![0].dependencies = [packageData]
export const { data, problems } = types.package(packageData)</pre></div>
<h2>API</h2>
<p>ArkType supports many of TypeScript's built-in types and operators, as well as some new nes dedicated exclusively to runtime validation. In fact, we got a little ahead of ourselves and built a ton of cool features, but we're still working on getting caught up syntax and API docs. Keep an eye out for more in the next couple weeks! In the meantime, check out the examples from this README and use the type hints you get to learn how you can customize your types and scopes. If you have any questions, don't hesitate to reach out on our <a href="https://discord.gg/WSNF3Kc4xh">Discord channel</a>!</p>
<h2>Contributing</h2>
<p>If you're interested in contributing to ArkType...</p>
<ol>
<li>Thank you! We'll do everything we can to make this as straightforward as possible, regardless of your level of experience.</li>
<li>Check out our <a href="/arktypeio/arktype/blob/main/dev/configs/CONTRIBUTING.md">guide</a> to get started!</li>
</ol>
<h3>How</h3>
<p>(<code>TODO</code>)</p>
<p><a href="https://camo.githubusercontent.com/b50a4ad771d0e0b8c7f47c4f6f172504d9fd3a259e2beeb0ce892ebfd3b12f2d/68747470733a2f2f6d65646961322e67697068792e636f6d2f6d656469612f434159565a41354e52623532396b4b5155632f67697068792e6769663f6369643d656366303565343773646f3479737138796c39376a3778666f35737233633265336534696d366970737063693576306b267269643d67697068792e676966"></a></p>
<h2>License</h2>
<p>This project is licensed under the terms of the
<a href="/arktypeio/arktype/blob/main/LICENSE">MIT license</a>.</p>
</article>
 </div>||||I|||| Skip to content
 Toggle navigation
 Sign up
 * Product
 + Actions
 Automate any workflow
 + Packages
 Host and manage packages
 + Security
 Find and fix vulnerabilities
 + Codespaces
 Instant dev environments
 + Copilot
 Write better code with AI
 + Code review
 Manage code changes
 + Issues
 Plan and track work
 + Discussions
 Collaborate outside of code
 + Explore
 + All features
 + Documentation
 + GitHub Skills
 + Blog
 * Solutions
 + For
 + Enterprise
 + Teams
 + Startups
 + Education
 + By Solution
 + CI/CD & Automation
 + DevOps
 + DevSecOps
 + Case Studies
 + Customer Stories
 + Resources
 * Open Source
 + GitHub Sponsors
 Fund open source developers
 + The ReadME Project
 GitHub community articles
 + Repositories
 + Topics
 + Trending
 + Collections
 * Pricing
 * In this repository All GitHub ↵
 Jump to ↵
 * No suggested jump to results
 * In this repository All GitHub ↵
 Jump to ↵
 * In this organization All GitHub ↵
 Jump to ↵
 * In this repository All GitHub ↵
 Jump to ↵
 Sign in
 Sign up
 {{ message }}
 arktypeio / arktype Public
 * Notifications
 * Fork 3
 * Star 76

 The first isomorphic type system for TS/JS

 arktype.io

 License

 MIT license
 76 stars 3 forks
 Star
 Notifications
 * Code
 * Issues 68
 * Pull requests 0
 * Actions
 * Projects 1
 * Security
 * Insights
 More
 * Code
 * Issues
 * Pull requests
 * Actions
 * Projects
 * Security
 * Insights

 arktypeio/arktype

 This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
 main
 Switch branches/tags
 Branches Tags
 Could not load branches
 Nothing to show
 {{ refName }} default
 View all branches
 Could not load tags
 Nothing to show
 {{ refName }} default
 View all tags

 Name already in use

 A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
 Cancel Create
 4 branches 16 tags
 Code
 * Local
 * Codespaces
 * Clone
 HTTPS GitHub CLI

 Use Git or checkout with SVN using the web URL.

 Work fast with our official CLI. Learn more.

 * Open with GitHub Desktop
 * Download ZIP

 Sign In Required

 Please sign in to use Codespaces.

 Launching GitHub Desktop

 If nothing happens, download GitHub Desktop and try again.

 Launching GitHub Desktop

 If nothing happens, download GitHub Desktop and try again.

 Launching Xcode

 If nothing happens, download Xcode and try again.

 Launching Visual Studio Code

 Your codespace will open once ready.

 There was a problem preparing your codespace, please try again.

 Latest commit

 Git stats

 * 656 commits

 Files

 Permalink
 Failed to load latest commit information.
 Type
 Name
 Latest commit message
 Commit time
 .changeset
 .github
 .vscode
 dev
 src
 .gitignore
 LICENSE
 README.md
 package.json
 tsconfig.json
 View code
 ArkType Install 📦4KB gzipped, 0 dependencies Types Scopes API Contributing How License

 README.md

 ArkType Isomorphic types for TS/JS

 typescript@4.9.5 in VS Code— no extensions or plugins required (how?)

 Install 📦4KB gzipped, 0 dependencies

 npm install arktype (or whatever package manager you prefer)

 import { type } from "https://deno.land/x/arktype"

 Try it in-browser at arktype.io/try (the types aren't quite as snappy as they will be in your IDE)

 Our types are tested in strict-mode with TypeScript versions 4.8, 4.9, and 5.0.

 Our APIs have mostly stabilized, but details may still change during the alpha/beta stages of our 1.0 release. If you have suggestions that may require a breaking change, now is the time to let us know! ⛵

 Types

 Try it in-browser.

 import { type } from "arktype"
 
 // Define a type...
 export const user = type({
 name: "string",
 device: {
 platform: "'android'|'ios'",
 "version?": "number"
 }
 })
 
 // Infer it...
 export type User = typeof user.infer
 
 // Validate your data anytime, anywhere, with the same clarity and precision you expect from TypeScript.
 export const { data, problems } = user({
 name: "Alan Turing",
 device: {
 platform: "enigma"
 }
 })
 
 if (problems) {
 // "device/platform must be 'android' or 'ios' (was 'enigma')"
 console.log(problems.summary)
 }

 Scopes

 Try it in-browser.

 import { scope } from "arktype"
 
 // Scopes are collections of types that can reference each other.
 export const types = scope({
 package: {
 name: "string",
 "dependencies?": "package[]",
 "contributors?": "contributor[]"
 },
 contributor: {
 // Subtypes like 'email' are inferred like 'string' but provide additional validation at runtime.
 email: "email",
 "packages?": "package[]"
 }
 }).compile()
 
 // Cyclic types are inferred to arbitrary depth...
 export type Package = typeof types.package.infer
 
 // And can validate cyclic data.
 const packageData: Package = {
 name: "arktype",
 dependencies: [{ name: "typescript" }],
 contributors: [{ email: "david@sharktypeio" }]
 }
 packageData.dependencies![0].dependencies = [packageData]
 
 export const { data, problems } = types.package(packageData)

 API

 ArkType supports many of TypeScript's built-in types and operators, as well as some new nes dedicated exclusively to runtime validation. In fact, we got a little ahead of ourselves and built a ton of cool features, but we're still working on getting caught up syntax and API docs. Keep an eye out for more in the next couple weeks! In the meantime, check out the examples from this README and use the type hints you get to learn how you can customize your types and scopes. If you have any questions, don't hesitate to reach out on our Discord channel!

 Contributing

 If you're interested in contributing to ArkType...

 1. Thank you! We'll do everything we can to make this as straightforward as possible, regardless of your level of experience.
 2. Check out our guide to get started!

 How

 (TODO)

 License

 This project is licensed under the terms of the MIT license.

 About

 The first isomorphic type system for TS/JS

 arktype.io

 Topics

 typescript parsing static-typing runtime-typechecking

 Resources

 Readme

 License

 MIT license

 Stars

 76 stars

 Watchers

 1 watching

 Forks

 3 forks

 Releases 14

 v1.0.3-alpha Latest
 Feb 23, 2023
 + 13 releases

 Packages 0

 No packages published

 Contributors 7

 * 
 * 
 * 
 * 
 * 
 * 
 * 

 Languages

 * TypeScript 97.8%
 * JavaScript 1.6%
 * Other 0.6%

 Footer

 © 2023 GitHub, Inc.

 Footer navigation

 * Terms
 * Privacy
 * Security
 * Status
 * Docs
 * Contact GitHub
 * Pricing
 * API
 * Training
 * Blog
 * About
 You can’t perform that action at this time.
 You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
GitHub - arktypeio/arktype: The first isomorphic type system for TS/JS
https://github.com/arktypeio/arktype
None
2020-01-01T00:00:00Z
<div><section><article><p>
  
  </p><h2>Zod</h2>
  <p>
    ✨ <a href="https://zod.dev">https://zod.dev</a> ✨
    <br/>
    TypeScript-first schema validation with static type inference
  </p>


<p>
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amain"></a>
<a href="https://twitter.com/colinhacks"></a>
<a href="https://opensource.org/licenses/MIT"></a>
<a href="https://www.npmjs.com/package/zod"></a>
<a href="https://www.npmjs.com/package/zod"></a>
</p>



<p><a href="https://go.clerk.com/hqN4rp7"></a></p><br/>

<h2><a href="https://zod.dev/?id=table-of-contents"><span>Table of contents</span></a></h2><blockquote>
<p>These docs have been translated into <a href="https://zod.dev/README_ZH">Chinese</a>.</p></blockquote>
<ul><li><a href="https://zod.dev/?id=table-of-contents">Table of contents</a></li><li><a href="https://zod.dev/?id=introduction">Introduction</a><ul><li><a href="https://zod.dev/?id=sponsors">Sponsors</a><ul><li><a href="https://zod.dev/?id=platinum">Platinum</a></li><li><a href="https://zod.dev/?id=gold">Gold</a></li><li><a href="https://zod.dev/?id=silver">Silver</a></li><li><a href="https://zod.dev/?id=bronze">Bronze</a></li><li><a href="https://zod.dev/?id=copper">Copper</a></li></ul></li><li><a href="https://zod.dev/?id=ecosystem">Ecosystem</a><ul><li><a href="https://zod.dev/?id=resources">Resources</a></li><li><a href="https://zod.dev/?id=api-libraries">API libraries</a></li><li><a href="https://zod.dev/?id=form-integrations">Form integrations</a></li><li><a href="https://zod.dev/?id=zod-to-x">Zod to X</a></li><li><a href="https://zod.dev/?id=x-to-zod">X to Zod</a></li><li><a href="https://zod.dev/?id=mocking">Mocking</a></li><li><a href="https://zod.dev/?id=powered-by-zod">Powered by Zod</a></li><li><a href="https://zod.dev/?id=utilities-for-zod">Utilities for Zod</a></li></ul></li></ul></li><li><a href="https://zod.dev/?id=installation">Installation</a><ul><li><a href="https://zod.dev/?id=requirements">Requirements</a></li><li><a href="https://zod.dev/?id=from-npm-nodebun">From <code>npm</code> (Node/Bun)</a></li><li><a href="https://zod.dev/?id=from-denolandx-deno">From <code>deno.land/x</code> (Deno)</a></li></ul></li><li><a href="https://zod.dev/?id=basic-usage">Basic usage</a></li><li><a href="https://zod.dev/?id=primitives">Primitives</a></li><li><a href="https://zod.dev/?id=coercion-for-primitives">Coercion for primitives</a></li><li><a href="https://zod.dev/?id=literals">Literals</a></li><li><a href="https://zod.dev/?id=strings">Strings</a><ul><li><a href="https://zod.dev/?id=datetimes">Datetimes</a></li><li><a href="https://zod.dev/?id=dates">Dates</a></li><li><a href="https://zod.dev/?id=times">Times</a></li><li><a href="https://zod.dev/?id=ip-addresses">IP addresses</a></li></ul></li><li><a href="https://zod.dev/?id=numbers">Numbers</a></li><li><a href="https://zod.dev/?id=bigints">BigInts</a></li><li><a href="https://zod.dev/?id=nans">NaNs</a></li><li><a href="https://zod.dev/?id=booleans">Booleans</a></li><li><a href="https://zod.dev/?id=dates">Dates</a></li><li><a href="https://zod.dev/?id=zod-enums">Zod enums</a></li><li><a href="https://zod.dev/?id=native-enums">Native enums</a></li><li><a href="https://zod.dev/?id=optionals">Optionals</a></li><li><a href="https://zod.dev/?id=nullables">Nullables</a></li><li><a href="https://zod.dev/?id=objects">Objects</a><ul><li><a href="https://zod.dev/?id=shape"><code>.shape</code></a></li><li><a href="https://zod.dev/?id=keyof"><code>.keyof</code></a></li><li><a href="https://zod.dev/?id=extend"><code>.extend</code></a></li><li><a href="https://zod.dev/?id=merge"><code>.merge</code></a></li><li><a href="https://zod.dev/?id=pickomit"><code>.pick/.omit</code></a></li><li><a href="https://zod.dev/?id=partial"><code>.partial</code></a></li><li><a href="https://zod.dev/?id=deeppartial"><code>.deepPartial</code></a></li><li><a href="https://zod.dev/?id=required"><code>.required</code></a></li><li><a href="https://zod.dev/?id=passthrough"><code>.passthrough</code></a></li><li><a href="https://zod.dev/?id=strict"><code>.strict</code></a></li><li><a href="https://zod.dev/?id=strip"><code>.strip</code></a></li><li><a href="https://zod.dev/?id=catchall"><code>.catchall</code></a></li></ul></li><li><a href="https://zod.dev/?id=arrays">Arrays</a><ul><li><a href="https://zod.dev/?id=element"><code>.element</code></a></li><li><a href="https://zod.dev/?id=nonempty"><code>.nonempty</code></a></li><li><a href="https://zod.dev/?id=minmaxlength"><code>.min/.max/.length</code></a></li></ul></li><li><a href="https://zod.dev/?id=tuples">Tuples</a></li><li><a href="https://zod.dev/?id=unions">Unions</a></li><li><a href="https://zod.dev/?id=discriminated-unions">Discriminated unions</a></li><li><a href="https://zod.dev/?id=records">Records</a><ul><li><a href="https://zod.dev/?id=record-key-type">Record key type</a></li></ul></li><li><a href="https://zod.dev/?id=maps">Maps</a></li><li><a href="https://zod.dev/?id=sets">Sets</a></li><li><a href="https://zod.dev/?id=intersections">Intersections</a></li><li><a href="https://zod.dev/?id=recursive-types">Recursive types</a><ul><li><a href="https://zod.dev/?id=zodtype-with-zodeffects">ZodType with ZodEffects</a></li><li><a href="https://zod.dev/?id=json-type">JSON type</a></li><li><a href="https://zod.dev/?id=cyclical-objects">Cyclical objects</a></li></ul></li><li><a href="https://zod.dev/?id=promises">Promises</a></li><li><a href="https://zod.dev/?id=instanceof">Instanceof</a></li><li><a href="https://zod.dev/?id=functions">Functions</a></li><li><a href="https://zod.dev/?id=preprocess">Preprocess</a></li><li><a href="https://zod.dev/?id=custom-schemas">Custom schemas</a></li><li><a href="https://zod.dev/?id=schema-methods">Schema methods</a><ul><li><a href="https://zod.dev/?id=parse"><code>.parse</code></a></li><li><a href="https://zod.dev/?id=parseasync"><code>.parseAsync</code></a></li><li><a href="https://zod.dev/?id=safeparse"><code>.safeParse</code></a></li><li><a href="https://zod.dev/?id=safeparseasync"><code>.safeParseAsync</code></a></li><li><a href="https://zod.dev/?id=refine"><code>.refine</code></a><ul><li><a href="https://zod.dev/?id=arguments">Arguments</a></li><li><a href="https://zod.dev/?id=customize-error-path">Customize error path</a></li><li><a href="https://zod.dev/?id=asynchronous-refinements">Asynchronous refinements</a></li><li><a href="https://zod.dev/?id=relationship-to-transforms">Relationship to transforms</a></li></ul></li><li><a href="https://zod.dev/?id=superrefine"><code>.superRefine</code></a><ul><li><a href="https://zod.dev/?id=abort-early">Abort early</a></li><li><a href="https://zod.dev/?id=type-refinements">Type refinements</a></li></ul></li><li><a href="https://zod.dev/?id=transform"><code>.transform</code></a><ul><li><a href="https://zod.dev/?id=chaining-order">Chaining order</a></li><li><a href="https://zod.dev/?id=validating-during-transform">Validating during transform</a></li><li><a href="https://zod.dev/?id=relationship-to-refinements">Relationship to refinements</a></li><li><a href="https://zod.dev/?id=async-transforms">Async transforms</a></li></ul></li><li><a href="https://zod.dev/?id=default"><code>.default</code></a></li><li><a href="https://zod.dev/?id=describe"><code>.describe</code></a></li><li><a href="https://zod.dev/?id=catch"><code>.catch</code></a></li><li><a href="https://zod.dev/?id=optional"><code>.optional</code></a></li><li><a href="https://zod.dev/?id=nullable"><code>.nullable</code></a></li><li><a href="https://zod.dev/?id=nullish"><code>.nullish</code></a></li><li><a href="https://zod.dev/?id=array"><code>.array</code></a></li><li><a href="https://zod.dev/?id=promise"><code>.promise</code></a></li><li><a href="https://zod.dev/?id=or"><code>.or</code></a></li><li><a href="https://zod.dev/?id=and"><code>.and</code></a></li><li><a href="https://zod.dev/?id=brand"><code>.brand</code></a></li><li><a href="https://zod.dev/?id=readonly"><code>.readonly</code></a></li><li><a href="https://zod.dev/?id=pipe"><code>.pipe</code></a><ul><li><a href="https://zod.dev/?id=you-can-use-pipe-to-fix-common-issues-with-zcoerce">You can use <code>.pipe()</code> to fix common issues with <code>z.coerce</code>.</a></li></ul></li></ul></li><li><a href="https://zod.dev/?id=guides-and-concepts">Guides and concepts</a><ul><li><a href="https://zod.dev/?id=type-inference">Type inference</a></li><li><a href="https://zod.dev/?id=writing-generic-functions">Writing generic functions</a><ul><li><a href="https://zod.dev/?id=constraining-allowable-inputs">Constraining allowable inputs</a></li></ul></li><li><a href="https://zod.dev/?id=error-handling">Error handling</a></li><li><a href="https://zod.dev/?id=error-formatting">Error formatting</a></li></ul></li><li><a href="https://zod.dev/?id=comparison">Comparison</a><ul><li><a href="https://zod.dev/?id=joi">Joi</a></li><li><a href="https://zod.dev/?id=yup">Yup</a></li><li><a href="https://zod.dev/?id=io-ts">io-ts</a></li><li><a href="https://zod.dev/?id=runtypes">Runtypes</a></li><li><a href="https://zod.dev/?id=ow">Ow</a></li></ul></li><li><a href="https://zod.dev/?id=changelog">Changelog</a></li></ul><h2><a href="https://zod.dev/?id=introduction"><span>Introduction</span></a></h2><p>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 <code>string</code> to a complex nested object.</p><p>Zod is designed to be as developer-friendly as possible. The goal is to eliminate duplicative type declarations. With Zod, you declare a validator <em>once</em> and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.</p><p>Some other great aspects:</p><ul><li>Zero dependencies</li><li>Works in Node.js and all modern browsers</li><li>Tiny: 8kb minified + zipped</li><li>Immutable: methods (e.g. <code>.optional()</code>) return a new instance</li><li>Concise, chainable interface</li><li>Functional approach: <a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">parse, don't validate</a></li><li>Works with plain JavaScript too! You don't need to use TypeScript.</li></ul><p>Sponsorship at any level is appreciated and encouraged. If you built a paid product using Zod, consider one of the <a href="https://github.com/sponsors/colinhacks">corporate tiers</a>.</p><br/>
<h3>Diamond</h3>

<br/>

<div>
  <a href="https://go.clerk.com/PKHrcwh">
    
  </a>
  <p>
    The most comprehensive User Management Platform
    <br/>
    <a href="https://go.clerk.com/PKHrcwh">clerk.com</a>
  </p>
</div>

<h3>Platinum</h3>



<br/>

<h3>Gold</h3>

<table>
  <tbody><tr>
    <td>
      
      <br/>
      <a href="https://www.propelauth.com/">PropelAuth</a>
    </td>
    <td>
      
      <br/>
      <a href="https://cerbos.dev/">Cerbos</a>
    </td>
    <td>
      
      <br/>
      <a href="https://scalar.com/">Scalar</a>
    </td>
    <td>
      
      <br/>
      <a href="https://trigger.dev">Trigger.dev</a>
    </td>
    </tr><tr>
    <td>
      
      <br/>
      <a href="https://transloadit.com/?utm_source=zod&amp;utm_medium=refe
    rral&amp;utm_campaign=sponsorship&amp;utm_content=github">Transloadit</a>
    </td>
    <td>
      
      <br/>
      <a href="https://infisical.com">Infisical</a>
    </td>
    <td>
      
      <br/>
      <a href="https://whop.com/">Whop</a>
    </td>
    <td>
      
      <br/>
      <a href="https://cryptojobslist.com/">CryptoJobsList</a>
    </td>
    </tr><tr>
    <td>
      
      <br/>
      <a href="https://plain.com/">Plain.</a>
    </td>
    <td>
      
      <br/>
      <a href="https://inngest.com/">Inngest</a>
    </td>
    <td>
      
      <br/>
      <a href="https://storyblok.com/">Storyblok</a>
    </td>
    <td>
      
      <br/>
      <a href="https://mux.link/zod">Mux</a>
    </td>
  </tr>
</tbody></table>

<br/>

<h3>Silver</h3>

<table>
  <tbody><tr>
    <td>
      <a href="https://www.route4me.com/">
        
      </a>
    </td>
    <td>
      <a href="https://encore.dev">
        
      </a>
    </td>
    <td>
      <a href="https://www.replay.io/">
        
      </a>
    </td>
    <td>
      <a href="https://www.numeric.io">
        
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://marcatopartners.com">
        
      </a>
    </td>
    <td>
      <a href="https://interval.com">
        
      </a>
    </td>
    <td>
      <a href="https://seasoned.cc">
        
      </a>
    </td>
    <td>
      <a href="https://www.bamboocreative.nz/">
        
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://github.com/jasonLaster">
        
      </a>
    </td>
  </tr>
</tbody></table>

<h3>Bronze</h3>

<table>
  <tbody><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>
</tbody></table>

<h3><a href="https://zod.dev/?id=ecosystem"><span>Ecosystem</span></a></h3><p>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 <a href="https://twitter.com/colinhacks">on Twitter</a> or <a href="https://github.com/colinhacks/zod/discussions">start a Discussion</a>. I'll add it below and tweet it out.</p><h4><a href="https://zod.dev/?id=resources"><span>Resources</span></a></h4><ul><li><a href="https://www.totaltypescript.com/tutorials/zod">Total TypeScript Zod Tutorial</a> by <a href="https://twitter.com/mattpocockuk">@mattpocockuk</a></li><li><a href="https://www.youtube.com/watch?v=rY_XqfSHock">Fixing TypeScript's Blindspot: Runtime Typechecking</a> by <a href="https://twitter.com/jherr">@jherr</a></li></ul><h4><a href="https://zod.dev/?id=api-libraries"><span>API libraries</span></a></h4><ul><li><a href="https://github.com/trpc/trpc"><code>tRPC</code></a>: Build end-to-end typesafe APIs without GraphQL.</li><li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-nestjs"><code>@anatine/zod-nestjs</code></a>: Helper methods for using Zod in a NestJS project.</li><li><a href="https://github.com/flock-community/zod-endpoints"><code>zod-endpoints</code></a>: Contract-first strictly typed endpoints with Zod. OpenAPI compatible.</li><li><a href="https://github.com/evertdespiegeleer/zhttp"><code>zhttp</code></a>: An OpenAPI compatible, strictly typed http library with Zod input and response validation.</li><li><a href="https://github.com/SeasonedSoftware/domain-functions/"><code>domain-functions</code></a>: Decouple your business logic from your framework using composable functions. With first-class type inference from end to end powered by Zod schemas.</li><li><a href="https://github.com/ecyrbe/zodios"><code>@zodios/core</code></a>: A typescript API client with runtime and compile time validation backed by axios and zod.</li><li><a href="https://github.com/RobinTail/express-zod-api"><code>express-zod-api</code></a>: Build Express-based APIs with I/O schema validation and custom middlewares.</li><li><a href="https://github.com/sumukhbarve/monoduck/blob/main/src/tapiduck/README.md"><code>tapiduck</code></a>: End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler.</li><li><a href="https://github.com/JakeFenley/koa-zod-router"><code>koa-zod-router</code></a>: Create typesafe routes in Koa with I/O validation using Zod.</li><li><a href="https://github.com/RobinTail/zod-sockets"><code>zod-sockets</code></a>: Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs</li></ul><h4><a href="https://zod.dev/?id=form-integrations"><span>Form integrations</span></a></h4><ul><li><a href="https://github.com/react-hook-form/resolvers#zod"><code>react-hook-form</code></a>: A first-party Zod resolver for React Hook Form.</li><li><a href="https://github.com/causaly/zod-validation-error"><code>zod-validation-error</code></a>: Generate user-friendly error messages from <code>ZodError</code>s.</li><li><a href="https://github.com/robertLichtnow/zod-formik-adapter"><code>zod-formik-adapter</code></a>: A community-maintained Formik adapter for Zod.</li><li><a href="https://github.com/esamattis/react-zorm"><code>react-zorm</code></a>: Standalone <code>&lt;form&gt;</code> generation and validation for React using Zod.</li><li><a href="https://github.com/rileytomasek/zodix"><code>zodix</code></a>: Zod utilities for FormData and URLSearchParams in Remix loaders and actions.</li><li><a href="https://conform.guide/api/zod/parseWithZod"><code>conform</code></a>: A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js.</li><li><a href="https://github.com/kiliman/remix-params-helper"><code>remix-params-helper</code></a>: Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.</li><li><a href="https://github.com/glazy/formik-validator-zod"><code>formik-validator-zod</code></a>: Formik-compliant validator library that simplifies using Zod with Formik.</li><li><a href="https://github.com/aiji42/zod-i18n"><code>zod-i18n-map</code></a>: Useful for translating Zod error messages.</li><li><a href="https://github.com/fabian-hiller/modular-forms"><code>@modular-forms/solid</code></a>: Modular form library for SolidJS that supports Zod for validation.</li><li><a href="https://github.com/crutchcorn/houseform/"><code>houseform</code></a>: A React form library that uses Zod for validation.</li><li><a href="https://github.com/ciscoheat/sveltekit-superforms"><code>sveltekit-superforms</code></a>: Supercharged form library for SvelteKit with Zod validation.</li><li><a href="https://github.com/MonoidDev/mobx-zod-form"><code>mobx-zod-form</code></a>: Data-first form builder based on MobX &amp; Zod.</li><li><a href="https://github.com/logaretm/vee-validate/tree/main/packages/zod"><code>@vee-validate/zod</code></a>: Form library for Vue.js with Zod schema validation.</li></ul><h4><a href="https://zod.dev/?id=zod-to-x"><span>Zod to X</span></a></h4><ul><li><a href="https://github.com/sachinraja/zod-to-ts"><code>zod-to-ts</code></a>: Generate TypeScript definitions from Zod schemas.</li><li><a href="https://github.com/StefanTerdell/zod-to-json-schema"><code>zod-to-json-schema</code></a>: Convert your Zod schemas into <a href="https://json-schema.org/">JSON Schemas</a>.</li><li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi"><code>@anatine/zod-openapi</code></a>: Converts a Zod schema to an OpenAPI v3.x <code>SchemaObject</code>.</li><li><a href="https://github.com/DavidTimms/zod-fast-check"><code>zod-fast-check</code></a>: Generate <code>fast-check</code> arbitraries from Zod schemas.</li><li><a href="https://github.com/kbkk/abitia/tree/main/packages/zod-dto"><code>zod-dto</code></a>: Generate Nest.js DTOs from a Zod schema.</li><li><a href="https://github.com/turkerdev/fastify-type-provider-zod"><code>fastify-type-provider-zod</code></a>: Create Fastify type providers from Zod schemas.</li><li><a href="https://github.com/asteasolutions/zod-to-openapi"><code>zod-to-openapi</code></a>: Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints &amp; parameters.</li><li><a href="https://github.com/incetarik/nestjs-graphql-zod"><code>nestjs-graphql-zod</code></a>: Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.</li><li><a href="https://github.com/samchungy/zod-openapi"><code>zod-openapi</code></a>: Create full OpenAPI v3.x documentation from Zod schemas.</li><li><a href="https://github.com/samchungy/fastify-zod-openapi"><code>fastify-zod-openapi</code></a>: Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas.</li><li><a href="https://typeschema.com/"><code>typeschema</code></a>: Universal adapter for schema validation.</li></ul><h4><a href="https://zod.dev/?id=x-to-zod"><span>X to Zod</span></a></h4><ul><li><a href="https://github.com/fabien0102/ts-to-zod"><code>ts-to-zod</code></a>: Convert TypeScript definitions into Zod schemas.</li><li><a href="https://github.com/johngeorgewright/runtyping/tree/main/packages/zod"><code>@runtyping/zod</code></a>: Generate Zod from static types &amp; JSON schema.</li><li><a href="https://github.com/StefanTerdell/json-schema-to-zod"><code>json-schema-to-zod</code></a>: Convert your <a href="https://json-schema.org/">JSON Schemas</a> into Zod schemas. <a href="https://StefanTerdell.github.io/json-schema-to-zod-react/">Live demo</a>.</li><li><a href="https://github.com/rsinohara/json-to-zod"><code>json-to-zod</code></a>: Convert JSON objects into Zod schemas. <a href="https://rsinohara.github.io/json-to-zod-react/">Live demo</a>.</li><li><a href="https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema"><code>graphql-codegen-typescript-validation-schema</code></a>: GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.</li><li><a href="https://github.com/CarterGrimmeisen/zod-prisma"><code>zod-prisma</code></a>: Generate Zod schemas from your Prisma schema.</li><li><a href="https://github.com/Southclaws/supervillain"><code>Supervillain</code></a>: Generate Zod schemas from your Go structs.</li><li><a href="https://github.com/omar-dulaimi/prisma-zod-generator"><code>prisma-zod-generator</code></a>: Emit Zod schemas from your Prisma schema.</li><li><a href="https://orm.drizzle.team/docs/zod"><code>drizzle-zod</code></a>: Emit Zod schemas from your Drizzle schema.</li><li><a href="https://github.com/omar-dulaimi/prisma-trpc-generator"><code>prisma-trpc-generator</code></a>: Emit fully implemented tRPC routers and their validation schemas using Zod.</li><li><a href="https://github.com/chrishoermann/zod-prisma-types"><code>zod-prisma-types</code></a> Create Zod types from your Prisma models.</li><li><a href="https://app.quicktype.io/"><code>quicktype</code></a>: Convert JSON objects and JSON schemas into Zod schemas.</li><li><a href="https://github.com/saiichihashimoto/sanity-typed/tree/main/packages/zod"><code>@sanity-typed/zod</code></a>: Generate Zod Schemas from <a href="https://www.sanity.io/docs/schema-types">Sanity Schemas</a>.</li><li><a href="https://github.com/ivangreene/java-to-zod"><code>java-to-zod</code></a>: Convert POJOs to Zod schemas</li><li><a href="https://github.com/anymaniax/orval"><code>Orval</code></a>: Generate Zod schemas from OpenAPI schemas</li><li><a href="https://github.com/kubb-labs/kubb"><code>Kubb</code></a>: Generate SDKs and Zod schemas from your OpenAPI schemas</li></ul><h4><a href="https://zod.dev/?id=mocking"><span>Mocking</span></a></h4><ul><li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock"><code>@anatine/zod-mock</code></a>: Generate mock data from a Zod schema. Powered by <a href="https://github.com/faker-js/faker">faker.js</a>.</li><li><a href="https://github.com/dipasqualew/zod-mocking"><code>zod-mocking</code></a>: Generate mock data from your Zod schemas.</li><li><a href="https://github.com/timdeschryver/zod-fixture"><code>zod-fixture</code></a>: Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.</li><li><a href="https://zocker.sigrist.dev"><code>zocker</code></a>: Generate plausible mock-data from your schemas.</li><li><a href="https://github.com/ItMaga/zodock"><code>zodock</code></a> Generate mock data based on Zod schemas.</li><li><a href="https://github.com/soc221b/zod-schema-faker"><code>zod-schema-faker</code></a> Generates mock data from Zod schemas. Powered by <a href="https://github.com/faker-js/faker">@faker-js/faker</a> and <a href="https://github.com/fent/randexp.js">randexp.js</a></li></ul><h4><a href="https://zod.dev/?id=powered-by-zod"><span>Powered by Zod</span></a></h4><ul><li><a href="https://github.com/JacobWeisenburger/freerstore"><code>freerstore</code></a>: Firestore cost optimizer.</li><li><a href="https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference"><code>slonik</code></a>: Node.js Postgres client with strong Zod integration.</li><li><a href="https://github.com/mdbetancourt/soly"><code>soly</code></a>: Create CLI applications with zod.</li><li><a href="https://github.com/vadimdemedes/pastel"><code>pastel</code></a>: Create CLI applications with react, zod, and ink.</li><li><a href="https://github.com/sidwebworks/zod-xlsx"><code>zod-xlsx</code></a>: A xlsx based resource validator using Zod schemas.</li><li><a href="https://github.com/lostfictions/znv"><code>znv</code></a>: Type-safe environment parsing and validation for Node.js with Zod schemas.</li><li><a href="https://github.com/alexmarqs/zod-config"><code>zod-config</code></a>: Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.</li></ul><h4><a href="https://zod.dev/?id=utilities-for-zod"><span>Utilities for Zod</span></a></h4><ul><li><a href="https://github.com/JacobWeisenburger/zod_utilz"><code>zod_utilz</code></a>: Framework agnostic utilities for Zod.</li><li><a href="https://github.com/marilari88/zod-playground"><code>zod-playground</code></a>: A tool for learning and testing Zod schema validation functionalities. <a href="https://zod-playground.vercel.app/">Link</a>.</li><li><a href="https://github.com/nereumelo/zod-sandbox"><code>zod-sandbox</code></a>: Controlled environment for testing zod schemas. <a href="https://zod-sandbox.vercel.app/">Live demo</a>.</li><li><a href="https://github.com/schalkventer/zod-dev"><code>zod-dev</code></a>: Conditionally disables Zod runtime parsing in production.</li><li><a href="https://github.com/duplojs/duplojs-zod-accelerator"><code>zod-accelerator</code></a>: Accelerates Zod's throughput up to ~100x.</li></ul><h2><a href="https://zod.dev/?id=installation"><span>Installation</span></a></h2><h3><a href="https://zod.dev/?id=requirements"><span>Requirements</span></a></h3><ul><li><p>TypeScript 4.5+!</p></li><li><p>You must enable <code>strict</code> mode in your <code>tsconfig.json</code>. This is a best practice for all TypeScript projects.</p><pre><code><span>// tsconfig.json</span>
<span>{</span>
  <span>// ...</span>
  <span>"compilerOptions"</span><span>:</span> <span>{</span>
    <span>// ...</span>
    <span>"strict"</span><span>:</span> <span>true</span>
  <span>}</span>
<span>}</span></code></pre></li></ul><h3><a href="https://zod.dev/?id=from-npm-nodebun"><span>From <code>npm</code> (Node/Bun)</span></a></h3><pre><code>npm install zod       # npm
yarn add zod          # yarn
bun add zod           # bun
pnpm add zod          # pnpm</code></pre><p>Zod also publishes a canary version on every commit. To install the canary:</p><pre><code>npm install zod@canary       # npm
yarn add zod@canary          # yarn
bun add zod@canary           # bun
pnpm add zod@canary          # pnpm</code></pre><h3><a href="https://zod.dev/?id=from-denolandx-deno"><span>From <code>deno.land/x</code> (Deno)</span></a></h3><p>Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on <a href="https://deno.land/x">deno.land/x</a>. The latest version can be imported like so:</p><pre><code><span>import</span> <span>{</span> z <span>}</span> <span>from</span> <span>"https://deno.land/x/zod/mod.ts"</span><span>;</span></code></pre><p>You can also specify a particular version:</p><pre><code><span>import</span> <span>{</span> z <span>}</span> <span>from</span> <span>"https://deno.land/x/zod@v3.16.1/mod.ts"</span><span>;</span></code></pre><blockquote>
<p>The rest of this README assumes you are using npm and importing directly from the <code>"zod"</code> package.</p></blockquote>
<h2><a href="https://zod.dev/?id=basic-usage"><span>Basic usage</span></a></h2><p>Creating a simple string schema</p><pre><code><span>import</span> <span>{</span> z <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>// creating a schema for strings</span>
<span>const</span> mySchema <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>

<span>// parsing</span>
mySchema<span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span>
mySchema<span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; throws ZodError</span>

<span>// "safe" parsing (doesn't throw error if validation fails)</span>
mySchema<span>.</span><span>safeParse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; { success: true; data: "tuna" }</span>
mySchema<span>.</span><span>safeParse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; { success: false; error: ZodError }</span></code></pre><p>Creating an object schema</p><pre><code><span>import</span> <span>{</span> z <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>const</span> User <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  username<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

User<span>.</span><span>parse</span><span>(</span><span>{</span> username<span>:</span> <span>"Ludwig"</span> <span>}</span><span>)</span><span>;</span>

<span>// extract the inferred type</span>
<span><span>type</span></span> User <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> User<span>&gt;</span><span>;</span>
<span>// { username: string }</span></code></pre><h2><a href="https://zod.dev/?id=primitives"><span>Primitives</span></a></h2><pre><code><span>import</span> <span>{</span> z <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>// primitive values</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>symbol</span><span>(</span><span>)</span><span>;</span>

<span>// empty types</span>
z<span>.</span><span>undefined</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>null</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>void</span><span>(</span><span>)</span><span>;</span> <span>// accepts undefined</span>

<span>// catch-all types</span>
<span>// allows any value</span>
z<span>.</span><span>any</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>unknown</span><span>(</span><span>)</span><span>;</span>

<span>// never type</span>
<span>// allows no values</span>
z<span>.</span><span>never</span><span>(</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=coercion-for-primitives"><span>Coercion for primitives</span></a></h2><p>Zod now provides a more convenient way to coerce primitive values.</p><pre><code><span>const</span> schema <span>=</span> z<span>.</span>coerce<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
schema<span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span>
schema<span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; "12"</span></code></pre><p>During the parsing step, the input is passed through the <code>String()</code> function, which is a JavaScript built-in for coercing data into strings.</p><pre><code>schema<span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; "12"</span>
schema<span>.</span><span>parse</span><span>(</span><span>true</span><span>)</span><span>;</span> <span>// =&gt; "true"</span>
schema<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; "undefined"</span>
schema<span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; "null"</span></code></pre><p>The returned schema is a normal <code>ZodString</code> instance so you can use all string methods.</p><pre><code>z<span>.</span>coerce<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span></code></pre><p><strong>How coercion works</strong></p><p>All primitive types support coercion. Zod coerces all inputs using the built-in constructors: <code>String(input)</code>, <code>Number(input)</code>, <code>new Date(input)</code>, etc.</p><pre><code>z<span>.</span>coerce<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span> <span>// String(input)</span>
z<span>.</span>coerce<span>.</span><span>number</span><span>(</span><span>)</span><span>;</span> <span>// Number(input)</span>
z<span>.</span>coerce<span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span> <span>// Boolean(input)</span>
z<span>.</span>coerce<span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span> <span>// BigInt(input)</span>
z<span>.</span>coerce<span>.</span><span>date</span><span>(</span><span>)</span><span>;</span> <span>// new Date(input)</span></code></pre><p><strong>Note</strong> — Boolean coercion with <code>z.coerce.boolean()</code> may not work how you expect. Any <a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">truthy</a> value is coerced to <code>true</code>, and any <a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">falsy</a> value is coerced to <code>false</code>.</p><pre><code><span>const</span> schema <span>=</span> z<span>.</span>coerce<span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span> <span>// Boolean(input)</span>

schema<span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
schema<span>.</span><span>parse</span><span>(</span><span>"true"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
schema<span>.</span><span>parse</span><span>(</span><span>"false"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
schema<span>.</span><span>parse</span><span>(</span><span>1</span><span>)</span><span>;</span> <span>// =&gt; true</span>
schema<span>.</span><span>parse</span><span>(</span><span>[</span><span>]</span><span>)</span><span>;</span> <span>// =&gt; true</span>

schema<span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// =&gt; false</span>
schema<span>.</span><span>parse</span><span>(</span><span>""</span><span>)</span><span>;</span> <span>// =&gt; false</span>
schema<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; false</span>
schema<span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; false</span></code></pre><p>For more control over coercion logic, consider using <a href="https://zod.dev/?id=preprocess"><code>z.preprocess</code></a> or <a href="https://zod.dev/?id=pipe"><code>z.pipe()</code></a>.</p><h2><a href="https://zod.dev/?id=literals"><span>Literals</span></a></h2><p>Literal schemas represent a <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types">literal type</a>, like <code>"hello world"</code> or <code>5</code>.</p><pre><code><span>const</span> tuna <span>=</span> z<span>.</span><span>literal</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>
<span>const</span> twelve <span>=</span> z<span>.</span><span>literal</span><span>(</span><span>12</span><span>)</span><span>;</span>
<span>const</span> twobig <span>=</span> z<span>.</span><span>literal</span><span>(</span><span>2n</span><span>)</span><span>;</span> <span>// bigint literal</span>
<span>const</span> tru <span>=</span> z<span>.</span><span>literal</span><span>(</span><span>true</span><span>)</span><span>;</span>

<span>const</span> terrificSymbol <span>=</span> <span>Symbol</span><span>(</span><span>"terrific"</span><span>)</span><span>;</span>
<span>const</span> terrific <span>=</span> z<span>.</span><span>literal</span><span>(</span>terrificSymbol<span>)</span><span>;</span>

<span>// retrieve literal value</span>
tuna<span>.</span>value<span>;</span> <span>// "tuna"</span></code></pre><blockquote>
<p>Currently there is no support for Date literals in Zod. If you have a use case for this feature, please file an issue.</p></blockquote>
<h2><a href="https://zod.dev/?id=strings"><span>Strings</span></a></h2><p>Zod includes a handful of string-specific validations.</p><pre><code><span>// validations</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>emoji</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>uuid</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nanoid</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>cuid</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>cuid2</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ulid</span><span>(</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>regex</span><span>(</span>regex<span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>includes</span><span>(</span><span>string</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>startsWith</span><span>(</span><span>string</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>endsWith</span><span>(</span><span>string</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>)</span><span>;</span> <span>// ISO 8601; by default only `Z` timezone allowed</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>)</span><span>;</span> <span>// defaults to allow both IPv4 and IPv6</span>

<span>// transforms</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>trim</span><span>(</span><span>)</span><span>;</span> <span>// trim whitespace</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>toLowerCase</span><span>(</span><span>)</span><span>;</span> <span>// toLowerCase</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>toUpperCase</span><span>(</span><span>)</span><span>;</span> <span>// toUpperCase</span>

<span>// added in Zod 3.23</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span> <span>// ISO date format (YYYY-MM-DD)</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>)</span><span>;</span> <span>// ISO time format (HH:mm:ss[.SSSSSS])</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>duration</span><span>(</span><span>)</span><span>;</span> <span>// ISO 8601 duration</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>base64</span><span>(</span><span>)</span><span>;</span></code></pre><blockquote>
<p>Check out <a href="https://github.com/validatorjs/validator.js">validator.js</a> for a bunch of other useful string validation functions that can be used in conjunction with <a href="https://zod.dev/?id=refine">Refinements</a>.</p></blockquote>
<p>You can customize some common error messages when creating a string schema.</p><pre><code><span>const</span> name <span>=</span> z<span>.</span><span>string</span><span>(</span><span>{</span>
  required_error<span>:</span> <span>"Name is required"</span><span>,</span>
  invalid_type_error<span>:</span> <span>"Name must be a string"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>When using validation methods, you can pass in an additional argument to provide a custom error message.</p><pre><code>z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>,</span> <span>{</span> message<span>:</span> <span>"Must be 5 or more characters long"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>,</span> <span>{</span> message<span>:</span> <span>"Must be 5 or fewer characters long"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>,</span> <span>{</span> message<span>:</span> <span>"Must be exactly 5 characters long"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid email address"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid url"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>emoji</span><span>(</span><span>{</span> message<span>:</span> <span>"Contains non-emoji characters"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>uuid</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid UUID"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>includes</span><span>(</span><span>"tuna"</span><span>,</span> <span>{</span> message<span>:</span> <span>"Must include tuna"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>startsWith</span><span>(</span><span>"https://"</span><span>,</span> <span>{</span> message<span>:</span> <span>"Must provide secure URL"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>endsWith</span><span>(</span><span>".com"</span><span>,</span> <span>{</span> message<span>:</span> <span>"Only .com domains allowed"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid datetime string! Must be UTC."</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid date string!"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid time string!"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> message<span>:</span> <span>"Invalid IP address"</span> <span>}</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=datetimes"><span>Datetimes</span></a></h3><p>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.</p><p>The <code>z.string().datetime()</code> method enforces ISO 8601; default is no timezone offsets and arbitrary sub-second decimal precision.</p><pre><code><span>const</span> datetime <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>)</span><span>;</span>

datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// pass</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123Z"</span><span>)</span><span>;</span> <span>// pass</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123456Z"</span><span>)</span><span>;</span> <span>// pass (arbitrary precision)</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00+02:00"</span><span>)</span><span>;</span> <span>// fail (no offsets allowed)</span></code></pre><p>Timezone offsets can be allowed by setting the <code>offset</code> option to <code>true</code>.</p><pre><code><span>const</span> datetime <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> offset<span>:</span> <span>true</span> <span>}</span><span>)</span><span>;</span>

datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00+02:00"</span><span>)</span><span>;</span> <span>// pass</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+02:00"</span><span>)</span><span>;</span> <span>// pass (millis optional)</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+0200"</span><span>)</span><span>;</span> <span>// pass (millis optional)</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+02"</span><span>)</span><span>;</span> <span>// pass (only offset hours)</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// pass (Z still supported)</span></code></pre><p>You can additionally constrain the allowable <code>precision</code>. By default, arbitrary sub-second precision is supported (but optional).</p><pre><code><span>const</span> datetime <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> precision<span>:</span> <span>3</span> <span>}</span><span>)</span><span>;</span>

datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123Z"</span><span>)</span><span>;</span> <span>// pass</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// fail</span>
datetime<span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123456Z"</span><span>)</span><span>;</span> <span>// fail</span></code></pre><h3><a href="https://zod.dev/?id=dates"><span>Dates</span></a></h3><blockquote>
<p>Added in Zod 3.23</p></blockquote>
<p>The <code>z.string().date()</code> method validates strings in the format <code>YYYY-MM-DD</code>.</p><pre><code><span>const</span> date <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>

date<span>.</span><span>parse</span><span>(</span><span>"2020-01-01"</span><span>)</span><span>;</span> <span>// pass</span>
date<span>.</span><span>parse</span><span>(</span><span>"2020-1-1"</span><span>)</span><span>;</span> <span>// fail</span>
date<span>.</span><span>parse</span><span>(</span><span>"2020-01-32"</span><span>)</span><span>;</span> <span>// fail</span></code></pre><h3><a href="https://zod.dev/?id=times"><span>Times</span></a></h3><blockquote>
<p>Added in Zod 3.23</p></blockquote>
<p>The <code>z.string().time()</code> method validates strings in the format <code>HH:MM:SS[.s+]</code>. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind.</p><pre><code><span>const</span> time <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>)</span><span>;</span>

time<span>.</span><span>parse</span><span>(</span><span>"00:00:00"</span><span>)</span><span>;</span> <span>// pass</span>
time<span>.</span><span>parse</span><span>(</span><span>"09:52:31"</span><span>)</span><span>;</span> <span>// pass</span>
time<span>.</span><span>parse</span><span>(</span><span>"23:59:59.9999999"</span><span>)</span><span>;</span> <span>// pass (arbitrary precision)</span>

time<span>.</span><span>parse</span><span>(</span><span>"00:00:00.123Z"</span><span>)</span><span>;</span> <span>// fail (no `Z` allowed)</span>
time<span>.</span><span>parse</span><span>(</span><span>"00:00:00.123+02:00"</span><span>)</span><span>;</span> <span>// fail (no offsets allowed)</span></code></pre><p>You can set the <code>precision</code> option to constrain the allowable decimal precision.</p><pre><code><span>const</span> time <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>{</span> precision<span>:</span> <span>3</span> <span>}</span><span>)</span><span>;</span>

time<span>.</span><span>parse</span><span>(</span><span>"00:00:00.123"</span><span>)</span><span>;</span> <span>// pass</span>
time<span>.</span><span>parse</span><span>(</span><span>"00:00:00.123456"</span><span>)</span><span>;</span> <span>// fail</span>
time<span>.</span><span>parse</span><span>(</span><span>"00:00:00"</span><span>)</span><span>;</span> <span>// fail</span></code></pre><h3><a href="https://zod.dev/?id=ip-addresses"><span>IP addresses</span></a></h3><p>The <code>z.string().ip()</code> method by default validate IPv4 and IPv6.</p><pre><code><span>const</span> ip <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>)</span><span>;</span>

ip<span>.</span><span>parse</span><span>(</span><span>"192.168.1.1"</span><span>)</span><span>;</span> <span>// pass</span>
ip<span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// pass</span>
ip<span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:192.168.1.1"</span><span>)</span><span>;</span> <span>// pass</span>

ip<span>.</span><span>parse</span><span>(</span><span>"256.1.1.1"</span><span>)</span><span>;</span> <span>// fail</span>
ip<span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:gggg:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// fail</span></code></pre><p>You can additionally set the IP <code>version</code>.</p><pre><code><span>const</span> ipv4 <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> version<span>:</span> <span>"v4"</span> <span>}</span><span>)</span><span>;</span>
ipv4<span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// fail</span>

<span>const</span> ipv6 <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> version<span>:</span> <span>"v6"</span> <span>}</span><span>)</span><span>;</span>
ipv6<span>.</span><span>parse</span><span>(</span><span>"192.168.1.1"</span><span>)</span><span>;</span> <span>// fail</span></code></pre><h2><a href="https://zod.dev/?id=numbers"><span>Numbers</span></a></h2><p>You can customize certain error messages when creating a number schema.</p><pre><code><span>const</span> age <span>=</span> z<span>.</span><span>number</span><span>(</span><span>{</span>
  required_error<span>:</span> <span>"Age is required"</span><span>,</span>
  invalid_type_error<span>:</span> <span>"Age must be a number"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>Zod includes a handful of number-specific validations.</p><pre><code>z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>gt</span><span>(</span><span>5</span><span>)</span><span>;</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>gte</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// alias .min(5)</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lt</span><span>(</span><span>5</span><span>)</span><span>;</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// alias .max(5)</span>

z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>int</span><span>(</span><span>)</span><span>;</span> <span>// value must be an integer</span>

z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>positive</span><span>(</span><span>)</span><span>;</span> <span>//     &gt; 0</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>nonnegative</span><span>(</span><span>)</span><span>;</span> <span>//  &gt;= 0</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>negative</span><span>(</span><span>)</span><span>;</span> <span>//     &lt; 0</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>nonpositive</span><span>(</span><span>)</span><span>;</span> <span>//  &lt;= 0</span>

z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>multipleOf</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// Evenly divisible by 5. Alias .step(5)</span>

z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>finite</span><span>(</span><span>)</span><span>;</span> <span>// value must be finite, not Infinity or -Infinity</span>
z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>safe</span><span>(</span><span>)</span><span>;</span> <span>// value must be between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER</span></code></pre><p>Optionally, you can pass in a second argument to provide a custom error message.</p><pre><code>z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5</span><span>,</span> <span>{</span> message<span>:</span> <span>"this👏is👏too👏big"</span> <span>}</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=bigints"><span>BigInts</span></a></h2><p>Zod includes a handful of bigint-specific validations.</p><pre><code>z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>gt</span><span>(</span><span>5n</span><span>)</span><span>;</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>gte</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// alias `.min(5n)`</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>lt</span><span>(</span><span>5n</span><span>)</span><span>;</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// alias `.max(5n)`</span>

z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>positive</span><span>(</span><span>)</span><span>;</span> <span>// &gt; 0n</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>nonnegative</span><span>(</span><span>)</span><span>;</span> <span>// &gt;= 0n</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>negative</span><span>(</span><span>)</span><span>;</span> <span>// &lt; 0n</span>
z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>nonpositive</span><span>(</span><span>)</span><span>;</span> <span>// &lt;= 0n</span>

z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>multipleOf</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// Evenly divisible by 5n.</span></code></pre><h2><a href="https://zod.dev/?id=nans"><span>NaNs</span></a></h2><p>You can customize certain error messages when creating a nan schema.</p><pre><code><span>const</span> isNaN <span>=</span> z<span>.</span><span>nan</span><span>(</span><span>{</span>
  required_error<span>:</span> <span>"isNaN is required"</span><span>,</span>
  invalid_type_error<span>:</span> <span>"isNaN must be 'not a number'"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=booleans"><span>Booleans</span></a></h2><p>You can customize certain error messages when creating a boolean schema.</p><pre><code><span>const</span> isActive <span>=</span> z<span>.</span><span>boolean</span><span>(</span><span>{</span>
  required_error<span>:</span> <span>"isActive is required"</span><span>,</span>
  invalid_type_error<span>:</span> <span>"isActive must be a boolean"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=dates-1"><span>Dates</span></a></h2><p>Use z.date() to validate <code>Date</code> instances.</p><pre><code>z<span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>safeParse</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// success: true</span>
z<span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>safeParse</span><span>(</span><span>"2022-01-12T00:00:00.000Z"</span><span>)</span><span>;</span> <span>// success: false</span></code></pre><p>You can customize certain error messages when creating a date schema.</p><pre><code><span>const</span> myDateSchema <span>=</span> z<span>.</span><span>date</span><span>(</span><span>{</span>
  required_error<span>:</span> <span>"Please select a date and time"</span><span>,</span>
  invalid_type_error<span>:</span> <span>"That's not a date!"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>Zod provides a handful of date-specific validations.</p><pre><code>z<span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>"1900-01-01"</span><span>)</span><span>,</span> <span>{</span> message<span>:</span> <span>"Too old"</span> <span>}</span><span>)</span><span>;</span>
z<span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>)</span><span>,</span> <span>{</span> message<span>:</span> <span>"Too young!"</span> <span>}</span><span>)</span><span>;</span></code></pre><p><strong>Coercion to Date</strong></p><p>Since <a href="https://github.com/colinhacks/zod/releases/tag/v3.20">zod 3.20</a>, use <a href="https://zod.dev/?id=coercion-for-primitives"><code>z.coerce.date()</code></a> to pass the input through <code>new Date(input)</code>.</p><pre><code><span>const</span> dateSchema <span>=</span> z<span>.</span>coerce<span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>DateSchema</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> dateSchema<span>&gt;</span><span>;</span>
<span>// type DateSchema = Date</span>

<span>/* valid dates */</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>"2023-01-10T00:00:00.000Z"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>"2023-01-10"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>"1/10/23"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>"1/10/23"</span><span>)</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>

<span>/* invalid dates */</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>"2023-13-10"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// false</span>
<span>console</span><span>.</span><span>log</span><span>(</span>dateSchema<span>.</span><span>safeParse</span><span>(</span><span>"0000-00-00"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// false</span></code></pre><p>For older zod versions, use <a href="https://zod.dev/?id=preprocess"><code>z.preprocess</code></a> like <a href="https://github.com/colinhacks/zod/discussions/879#discussioncomment-2036276">described in this thread</a>.</p><h2><a href="https://zod.dev/?id=zod-enums"><span>Zod enums</span></a></h2><pre><code><span>const</span> FishEnum <span>=</span> z<span>.</span><span>enum</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>type</span> <span>FishEnum</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> FishEnum<span>&gt;</span><span>;</span>
<span>// 'Salmon' | 'Tuna' | 'Trout'</span></code></pre><p><code>z.enum</code> is a Zod-native way to declare a schema with a fixed set of allowable <em>string</em> values. Pass the array of values directly into <code>z.enum()</code>. Alternatively, use <code>as const</code> to define your enum values as a tuple of strings. See the <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions">const assertion docs</a> for details.</p><pre><code><span>const</span> <span>VALUES</span> <span>=</span> <span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span> <span>as</span> <span>const</span><span>;</span>
<span>const</span> FishEnum <span>=</span> z<span>.</span><span>enum</span><span>(</span><span>VALUES</span><span>)</span><span>;</span></code></pre><p>This is not allowed, since Zod isn't able to infer the exact values of each element.</p><pre><code><span>const</span> fish <span>=</span> <span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>;</span>
<span>const</span> FishEnum <span>=</span> z<span>.</span><span>enum</span><span>(</span>fish<span>)</span><span>;</span></code></pre><p><strong><code>.enum</code></strong></p><p>To get autocompletion with a Zod enum, use the <code>.enum</code> property of your schema:</p><pre><code>FishEnum<span>.</span>enum<span>.</span>Salmon<span>;</span> <span>// =&gt; autocompletes</span>

FishEnum<span>.</span>enum<span>;</span>
<span>/*
=&gt; {
  Salmon: "Salmon",
  Tuna: "Tuna",
  Trout: "Trout",
}
*/</span></code></pre><p>You can also retrieve the list of options as a tuple with the <code>.options</code> property:</p><pre><code>FishEnum<span>.</span>options<span>;</span> <span>// ["Salmon", "Tuna", "Trout"];</span></code></pre><p><strong><code>.exclude/.extract()</code></strong></p><p>You can create subsets of a Zod enum with the <code>.exclude</code> and <code>.extract</code> methods.</p><pre><code><span>const</span> FishEnum <span>=</span> z<span>.</span><span>enum</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>const</span> SalmonAndTrout <span>=</span> FishEnum<span>.</span><span>extract</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>const</span> TunaOnly <span>=</span> FishEnum<span>.</span><span>exclude</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=native-enums"><span>Native enums</span></a></h2><p>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 <code>z.nativeEnum()</code>.</p><p><strong>Numeric enums</strong></p><pre><code><span>enum</span> Fruits <span>{</span>
  Apple<span>,</span>
  Banana<span>,</span>
<span>}</span>

<span>const</span> FruitEnum <span>=</span> z<span>.</span><span>nativeEnum</span><span>(</span>Fruits<span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> FruitEnum<span>&gt;</span><span>;</span> <span>// Fruits</span>

FruitEnum<span>.</span><span>parse</span><span>(</span>Fruits<span>.</span>Apple<span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span>Fruits<span>.</span>Banana<span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>1</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>3</span><span>)</span><span>;</span> <span>// fails</span></code></pre><p><strong>String enums</strong></p><pre><code><span>enum</span> Fruits <span>{</span>
  Apple <span>=</span> <span>"apple"</span><span>,</span>
  Banana <span>=</span> <span>"banana"</span><span>,</span>
  Cantaloupe<span>,</span> <span>// you can mix numerical and string enums</span>
<span>}</span>

<span>const</span> FruitEnum <span>=</span> z<span>.</span><span>nativeEnum</span><span>(</span>Fruits<span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> FruitEnum<span>&gt;</span><span>;</span> <span>// Fruits</span>

FruitEnum<span>.</span><span>parse</span><span>(</span>Fruits<span>.</span>Apple<span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span>Fruits<span>.</span>Cantaloupe<span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>"apple"</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>"banana"</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>"Cantaloupe"</span><span>)</span><span>;</span> <span>// fails</span></code></pre><p><strong>Const enums</strong></p><p>The <code>.nativeEnum()</code> function works for <code>as const</code> objects as well. ⚠️ <code>as const</code> requires TypeScript 3.4+!</p><pre><code><span>const</span> Fruits <span>=</span> <span>{</span>
  Apple<span>:</span> <span>"apple"</span><span>,</span>
  Banana<span>:</span> <span>"banana"</span><span>,</span>
  Cantaloupe<span>:</span> <span>3</span><span>,</span>
<span>}</span> <span>as</span> <span>const</span><span>;</span>

<span>const</span> FruitEnum <span>=</span> z<span>.</span><span>nativeEnum</span><span>(</span>Fruits<span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> FruitEnum<span>&gt;</span><span>;</span> <span>// "apple" | "banana" | 3</span>

FruitEnum<span>.</span><span>parse</span><span>(</span><span>"apple"</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>"banana"</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>3</span><span>)</span><span>;</span> <span>// passes</span>
FruitEnum<span>.</span><span>parse</span><span>(</span><span>"Cantaloupe"</span><span>)</span><span>;</span> <span>// fails</span></code></pre><p>You can access the underlying object with the <code>.enum</code> property:</p><pre><code>FruitEnum<span>.</span>enum<span>.</span>Apple<span>;</span> <span>// "apple"</span></code></pre><h2><a href="https://zod.dev/?id=optionals"><span>Optionals</span></a></h2><p>You can make any schema optional with <code>z.optional()</code>. This wraps the schema in a <code>ZodOptional</code> instance and returns the result.</p><pre><code><span>const</span> schema <span>=</span> z<span>.</span><span>optional</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>

schema<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; returns undefined</span>
<span>type</span> <span><span>A</span></span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> schema<span>&gt;</span><span>;</span> <span>// string | undefined</span></code></pre><p>For convenience, you can also call the <code>.optional()</code> method on an existing schema.</p><pre><code><span>const</span> user <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  username<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>type</span> <span><span>C</span></span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> user<span>&gt;</span><span>;</span> <span>// { username?: string | undefined };</span></code></pre><p>You can extract the wrapped schema from a <code>ZodOptional</code> instance with <code>.unwrap()</code>.</p><pre><code><span>const</span> stringSchema <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>const</span> optionalString <span>=</span> stringSchema<span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span>
optionalString<span>.</span><span>unwrap</span><span>(</span><span>)</span> <span>===</span> stringSchema<span>;</span> <span>// true</span></code></pre><h2><a href="https://zod.dev/?id=nullables"><span>Nullables</span></a></h2><p>Similarly, you can create nullable types with <code>z.nullable()</code>.</p><pre><code><span>const</span> nullableString <span>=</span> z<span>.</span><span>nullable</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
nullableString<span>.</span><span>parse</span><span>(</span><span>"asdf"</span><span>)</span><span>;</span> <span>// =&gt; "asdf"</span>
nullableString<span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; null</span></code></pre><p>Or use the <code>.nullable()</code> method.</p><pre><code><span>const</span> <span>E</span> <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span> <span>// equivalent to nullableString</span>
<span>type</span> <span><span>E</span></span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> <span>E</span><span>&gt;</span><span>;</span> <span>// string | null</span></code></pre><p>Extract the inner schema with <code>.unwrap()</code>.</p><pre><code><span>const</span> stringSchema <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>const</span> nullableString <span>=</span> stringSchema<span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span>
nullableString<span>.</span><span>unwrap</span><span>(</span><span>)</span> <span>===</span> stringSchema<span>;</span> <span>// true</span></code></pre><h2><a href="https://zod.dev/?id=objects"><span>Objects</span></a></h2><pre><code><span>// all properties are required by default</span>
<span>const</span> Dog <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  age<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>// extract the inferred type like this</span>
<span>type</span> <span>Dog</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> Dog<span>&gt;</span><span>;</span>

<span>// equivalent to:</span>
<span>type</span> <span>Dog</span> <span>=</span> <span>{</span>
  name<span>:</span> <span>string</span><span>;</span>
  age<span>:</span> <span>number</span><span>;</span>
<span>}</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=shape"><span><code>.shape</code></span></a></h3><p>Use <code>.shape</code> to access the schemas for a particular key.</p><pre><code>Dog<span>.</span>shape<span>.</span>name<span>;</span> <span>// =&gt; string schema</span>
Dog<span>.</span>shape<span>.</span>age<span>;</span> <span>// =&gt; number schema</span></code></pre><h3><a href="https://zod.dev/?id=keyof"><span><code>.keyof</code></span></a></h3><p>Use <code>.keyof</code> to create a <code>ZodEnum</code> schema from the keys of an object schema.</p><pre><code><span>const</span> keySchema <span>=</span> Dog<span>.</span><span>keyof</span><span>(</span><span>)</span><span>;</span>
keySchema<span>;</span> <span>// ZodEnum&lt;["name", "age"]&gt;</span></code></pre><h3><a href="https://zod.dev/?id=extend"><span><code>.extend</code></span></a></h3><p>You can add additional fields to an object schema with the <code>.extend</code> method.</p><pre><code><span>const</span> DogWithBreed <span>=</span> Dog<span>.</span><span>extend</span><span>(</span><span>{</span>
  breed<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>You can use <code>.extend</code> to overwrite fields! Be careful with this power!</p><h3><a href="https://zod.dev/?id=merge"><span><code>.merge</code></span></a></h3><p>Equivalent to <code>A.extend(B.shape)</code>.</p><pre><code><span>const</span> BaseTeacher <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> students<span>:</span> z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span> <span>}</span><span>)</span><span>;</span>
<span>const</span> HasID <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> id<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>;</span>

<span>const</span> Teacher <span>=</span> BaseTeacher<span>.</span><span>merge</span><span>(</span>HasID<span>)</span><span>;</span>
<span>type</span> <span>Teacher</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> Teacher<span>&gt;</span><span>;</span> <span>// =&gt; { students: string[], id: string }</span></code></pre><blockquote>
<p>If the two schemas share keys, the properties of B overrides the property of A. The returned schema also inherits the "unknownKeys" policy (strip/strict/passthrough) and the catchall schema of B.</p></blockquote>
<h3><a href="https://zod.dev/?id=pickomit"><span><code>.pick/.omit</code></span></a></h3><p>Inspired by TypeScript's built-in <code>Pick</code> and <code>Omit</code> utility types, all Zod object schemas have <code>.pick</code> and <code>.omit</code> methods that return a modified version. Consider this Recipe schema:</p><pre><code><span>const</span> Recipe <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  id<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  ingredients<span>:</span> z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>To only keep certain keys, use <code>.pick</code> .</p><pre><code><span>const</span> JustTheName <span>=</span> Recipe<span>.</span><span>pick</span><span>(</span><span>{</span> name<span>:</span> <span>true</span> <span>}</span><span>)</span><span>;</span>
<span>type</span> <span>JustTheName</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> JustTheName<span>&gt;</span><span>;</span>
<span>// =&gt; { name: string }</span></code></pre><p>To remove certain keys, use <code>.omit</code> .</p><pre><code><span>const</span> NoIDRecipe <span>=</span> Recipe<span>.</span><span>omit</span><span>(</span><span>{</span> id<span>:</span> <span>true</span> <span>}</span><span>)</span><span>;</span>

<span>type</span> <span>NoIDRecipe</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> NoIDRecipe<span>&gt;</span><span>;</span>
<span>// =&gt; { name: string, ingredients: string[] }</span></code></pre><h3><a href="https://zod.dev/?id=partial"><span><code>.partial</code></span></a></h3><p>Inspired by the built-in TypeScript utility type <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype">Partial</a>, the <code>.partial</code> method makes all properties optional.</p><p>Starting from this object:</p><pre><code><span>const</span> user <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  email<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  username<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// { email: string; username: string }</span></code></pre><p>We can create a partial version:</p><pre><code><span>const</span> partialUser <span>=</span> user<span>.</span><span>partial</span><span>(</span><span>)</span><span>;</span>
<span>// { email?: string | undefined; username?: string | undefined }</span></code></pre><p>You can also specify which properties to make optional:</p><pre><code><span>const</span> optionalEmail <span>=</span> user<span>.</span><span>partial</span><span>(</span><span>{</span>
  email<span>:</span> <span>true</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>/*
{
  email?: string | undefined;
  username: string
}
*/</span></code></pre><h3><a href="https://zod.dev/?id=deeppartial"><span><code>.deepPartial</code></span></a></h3><p>The <code>.partial</code> method is shallow — it only applies one level deep. There is also a "deep" version:</p><pre><code><span>const</span> user <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  username<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  location<span>:</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
    latitude<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
    longitude<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span>
  strings<span>:</span> z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>object</span><span>(</span><span>{</span> value<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> deepPartialUser <span>=</span> user<span>.</span><span>deepPartial</span><span>(</span><span>)</span><span>;</span>

<span>/*
{
  username?: string | undefined,
  location?: {
    latitude?: number | undefined;
    longitude?: number | undefined;
  } | undefined,
  strings?: { value?: string}[]
}
*/</span></code></pre><blockquote>
<p>Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.</p></blockquote>
<h3><a href="https://zod.dev/?id=required"><span><code>.required</code></span></a></h3><p>Contrary to the <code>.partial</code> method, the <code>.required</code> method makes all properties required.</p><p>Starting from this object:</p><pre><code><span>const</span> user <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    email<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    username<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>partial</span><span>(</span><span>)</span><span>;</span>
<span>// { email?: string | undefined; username?: string | undefined }</span></code></pre><p>We can create a required version:</p><pre><code><span>const</span> requiredUser <span>=</span> user<span>.</span><span>required</span><span>(</span><span>)</span><span>;</span>
<span>// { email: string; username: string }</span></code></pre><p>You can also specify which properties to make required:</p><pre><code><span>const</span> requiredEmail <span>=</span> user<span>.</span><span>required</span><span>(</span><span>{</span>
  email<span>:</span> <span>true</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>/*
{
  email: string;
  username?: string | undefined;
}
*/</span></code></pre><h3><a href="https://zod.dev/?id=passthrough"><span><code>.passthrough</code></span></a></h3><p>By default Zod object schemas strip out unrecognized keys during parsing.</p><pre><code><span>const</span> person <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

person<span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"bob dylan"</span><span>,</span>
  extraKey<span>:</span> <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; { name: "bob dylan" }</span>
<span>// extraKey has been stripped</span></code></pre><p>Instead, if you want to pass through unknown keys, use <code>.passthrough()</code> .</p><pre><code>person<span>.</span><span>passthrough</span><span>(</span><span>)</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"bob dylan"</span><span>,</span>
  extraKey<span>:</span> <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; { name: "bob dylan", extraKey: 61 }</span></code></pre><h3><a href="https://zod.dev/?id=strict"><span><code>.strict</code></span></a></h3><p>By default Zod object schemas strip out unrecognized keys during parsing. You can <em>disallow</em> unknown keys with <code>.strict()</code> . If there are any unknown keys in the input, Zod will throw an error.</p><pre><code><span>const</span> person <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>strict</span><span>(</span><span>)</span><span>;</span>

person<span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"bob dylan"</span><span>,</span>
  extraKey<span>:</span> <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; throws ZodError</span></code></pre><h3><a href="https://zod.dev/?id=strip"><span><code>.strip</code></span></a></h3><p>You can use the <code>.strip</code> method to reset an object schema to the default behavior (stripping unrecognized keys).</p><h3><a href="https://zod.dev/?id=catchall"><span><code>.catchall</code></span></a></h3><p>You can pass a "catchall" schema into an object schema. All unknown keys will be validated against it.</p><pre><code><span>const</span> person <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>catchall</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>

person<span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"bob dylan"</span><span>,</span>
  validExtraKey<span>:</span> <span>61</span><span>,</span> <span>// works fine</span>
<span>}</span><span>)</span><span>;</span>

person<span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"bob dylan"</span><span>,</span>
  validExtraKey<span>:</span> <span>false</span><span>,</span> <span>// fails</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; throws ZodError</span></code></pre><p>Using <code>.catchall()</code> obviates <code>.passthrough()</code> , <code>.strip()</code> , or <code>.strict()</code>. All keys are now considered "known".</p><h2><a href="https://zod.dev/?id=arrays"><span>Arrays</span></a></h2><pre><code><span>const</span> stringArray <span>=</span> z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// equivalent</span>
<span>const</span> stringArray <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span></code></pre><p>Be careful with the <code>.array()</code> method. It returns a new <code>ZodArray</code> instance. This means the <em>order</em> in which you call methods matters. For instance:</p><pre><code>z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span> <span>// (string | undefined)[]</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span> <span>// string[] | undefined</span></code></pre><h3><a href="https://zod.dev/?id=element"><span><code>.element</code></span></a></h3><p>Use <code>.element</code> to access the schema for an element of the array.</p><pre><code>stringArray<span>.</span>element<span>;</span> <span>// =&gt; string schema</span></code></pre><h3><a href="https://zod.dev/?id=nonempty"><span><code>.nonempty</code></span></a></h3><p>If you want to ensure that an array contains at least one element, use <code>.nonempty()</code>.</p><pre><code><span>const</span> nonEmptyStrings <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>)</span><span>;</span>
<span>// the inferred type is now</span>
<span>// [string, ...string[]]</span>

nonEmptyStrings<span>.</span><span>parse</span><span>(</span><span>[</span><span>]</span><span>)</span><span>;</span> <span>// throws: "Array cannot be empty"</span>
nonEmptyStrings<span>.</span><span>parse</span><span>(</span><span>[</span><span>"Ariana Grande"</span><span>]</span><span>)</span><span>;</span> <span>// passes</span></code></pre><p>You can optionally specify a custom error message:</p><pre><code><span>// optional custom error message</span>
<span>const</span> nonEmptyStrings <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>{</span>
  message<span>:</span> <span>"Can't be empty!"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=minmaxlength"><span><code>.min/.max/.length</code></span></a></h3><pre><code>z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or more items</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or fewer items</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 items exactly</span></code></pre><p>Unlike <code>.nonempty()</code> these methods do not change the inferred type.</p><h2><a href="https://zod.dev/?id=tuples"><span>Tuples</span></a></h2><p>Unlike arrays, tuples have a fixed number of elements and each element can have a different type.</p><pre><code><span>const</span> athleteSchema <span>=</span> z<span>.</span><span>tuple</span><span>(</span><span>[</span>
  z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>// name</span>
  z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>// jersey number</span>
  z<span>.</span><span>object</span><span>(</span><span>{</span>
    pointsScored<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span> <span>// statistics</span>
<span>]</span><span>)</span><span>;</span>

<span>type</span> <span>Athlete</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> athleteSchema<span>&gt;</span><span>;</span>
<span>// type Athlete = [string, number, { pointsScored: number }]</span></code></pre><p>A variadic ("rest") argument can be added with the <code>.rest</code> method.</p><pre><code><span>const</span> variadicTuple <span>=</span> z<span>.</span><span>tuple</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>]</span><span>)</span><span>.</span><span>rest</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>const</span> result <span>=</span> variadicTuple<span>.</span><span>parse</span><span>(</span><span>[</span><span>"hello"</span><span>,</span> <span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>]</span><span>)</span><span>;</span>
<span>// =&gt; [string, ...number[]];</span></code></pre><h2><a href="https://zod.dev/?id=unions"><span>Unions</span></a></h2><p>Zod includes a built-in <code>z.union</code> method for composing "OR" types.</p><pre><code><span>const</span> stringOrNumber <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>

stringOrNumber<span>.</span><span>parse</span><span>(</span><span>"foo"</span><span>)</span><span>;</span> <span>// passes</span>
stringOrNumber<span>.</span><span>parse</span><span>(</span><span>14</span><span>)</span><span>;</span> <span>// passes</span></code></pre><p>Zod will test the input against each of the "options" in order and return the first value that validates successfully.</p><p>For convenience, you can also use the <a href="https://zod.dev/?id=or"><code>.or</code> method</a>:</p><pre><code><span>const</span> stringOrNumber <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><p><strong>Optional string validation:</strong></p><p>To validate an optional form input, you can union the desired string validation with an empty string <a href="https://zod.dev/?id=literals">literal</a>.</p><p>This example validates an input that is optional but needs to contain a <a href="https://zod.dev/?id=strings">valid URL</a>:</p><pre><code><span>const</span> optionalUrl <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>)</span><span>.</span><span>nullish</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>literal</span><span>(</span><span>""</span><span>)</span><span>]</span><span>)</span><span>;</span>

<span>console</span><span>.</span><span>log</span><span>(</span>optionalUrl<span>.</span><span>safeParse</span><span>(</span><span>undefined</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>optionalUrl<span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>optionalUrl<span>.</span><span>safeParse</span><span>(</span><span>""</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>optionalUrl<span>.</span><span>safeParse</span><span>(</span><span>"https://zod.dev"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span>optionalUrl<span>.</span><span>safeParse</span><span>(</span><span>"not a valid url"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// false</span></code></pre><h2><a href="https://zod.dev/?id=discriminated-unions"><span>Discriminated unions</span></a></h2><p>A discriminated union is a union of object schemas that all share a particular key.</p><pre><code><span>type</span> <span>MyUnion</span> <span>=</span>
  <span>|</span> <span>{</span> status<span>:</span> <span>"success"</span><span>;</span> data<span>:</span> <span>string</span> <span>}</span>
  <span>|</span> <span>{</span> status<span>:</span> <span>"failed"</span><span>;</span> error<span>:</span> Error <span>}</span><span>;</span></code></pre><p>Such unions can be represented with the <code>z.discriminatedUnion</code> method. This enables faster evaluation, because Zod can check the <em>discriminator key</em> (<code>status</code> in the example above) to determine which schema should be used to parse the input. This makes parsing more efficient and lets Zod report friendlier errors.</p><p>With the basic union method, the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".</p><pre><code><span>const</span> myUnion <span>=</span> z<span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  z<span>.</span><span>object</span><span>(</span><span>{</span> status<span>:</span> z<span>.</span><span>literal</span><span>(</span><span>"success"</span><span>)</span><span>,</span> data<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>,</span>
  z<span>.</span><span>object</span><span>(</span><span>{</span> status<span>:</span> z<span>.</span><span>literal</span><span>(</span><span>"failed"</span><span>)</span><span>,</span> error<span>:</span> z<span>.</span><span>instanceof</span><span>(</span>Error<span>)</span> <span>}</span><span>)</span><span>,</span>
<span>]</span><span>)</span><span>;</span>

myUnion<span>.</span><span>parse</span><span>(</span><span>{</span> status<span>:</span> <span>"success"</span><span>,</span> data<span>:</span> <span>"yippie ki yay"</span> <span>}</span><span>)</span><span>;</span></code></pre><p>You can extract a reference to the array of schemas with the <code>.options</code> property.</p><pre><code>myUnion<span>.</span>options<span>;</span> <span>// [ZodObject&lt;...&gt;, ZodObject&lt;...&gt;]</span></code></pre><p>To merge two or more discriminated unions, use <code>.options</code> with destructuring.</p><pre><code><span>const</span> <span>A</span> <span>=</span> z<span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  <span>/* options */</span>
<span>]</span><span>)</span><span>;</span>
<span>const</span> <span>B</span> <span>=</span> z<span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  <span>/* options */</span>
<span>]</span><span>)</span><span>;</span>

<span>const</span> <span>AB</span> <span>=</span> z<span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span><span>...</span><span>A</span><span>.</span>options<span>,</span> <span>...</span><span>B</span><span>.</span>options<span>]</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=records"><span>Records</span></a></h2><p>Record schemas are used to validate types such as <code>Record&lt;string, number&gt;</code>. This is particularly useful for storing or caching items by ID.</p>

<pre><code><span>const</span> User <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>;</span>

<span>const</span> UserStore <span>=</span> z<span>.</span><span>record</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> User<span>)</span><span>;</span>
<span>type</span> <span>UserStore</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> UserStore<span>&gt;</span><span>;</span>
<span>// =&gt; Record&lt;string, { name: string }&gt;</span></code></pre><p>The schema and inferred type can be used like so:</p><pre><code><span>const</span> userStore<span>:</span> UserStore <span>=</span> <span>{</span><span>}</span><span>;</span>

userStore<span>[</span><span>"77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"</span><span>]</span> <span>=</span> <span>{</span>
  name<span>:</span> <span>"Carlotta"</span><span>,</span>
<span>}</span><span>;</span> <span>// passes</span>

userStore<span>[</span><span>"77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"</span><span>]</span> <span>=</span> <span>{</span>
  whatever<span>:</span> <span>"Ice cream sundae"</span><span>,</span>
<span>}</span><span>;</span> <span>// TypeError</span></code></pre><p><strong>A note on numerical keys</strong></p><p>While <code>z.record(keyType, valueType)</code> is able to accept numerical key types and TypeScript's built-in Record type is <code>Record&lt;KeyType, ValueType&gt;</code>, it's hard to represent the TypeScript type <code>Record&lt;number, any&gt;</code> in Zod.</p><p>As it turns out, TypeScript's behavior surrounding <code>[k: number]</code> is a little unintuitive:</p><pre><code><span>const</span> testMap<span>:</span> <span>{</span> <span>[</span>k<span>:</span> <span>number</span><span>]</span><span>:</span> <span>string</span> <span>}</span> <span>=</span> <span>{</span>
  <span>1</span><span>:</span> <span>"one"</span><span>,</span>
<span>}</span><span>;</span>

<span>for</span> <span>(</span><span>const</span> key <span>in</span> testMap<span>)</span> <span>{</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span><span>`</span><span><span>${</span>key<span>}</span></span><span>: </span><span><span>${</span><span>typeof</span> key<span>}</span></span><span>`</span></span><span>)</span><span>;</span>
<span>}</span>
<span>// prints: `1: string`</span></code></pre><p>As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.</p><h2><a href="https://zod.dev/?id=maps"><span>Maps</span></a></h2><pre><code><span>const</span> stringNumberMap <span>=</span> z<span>.</span><span>map</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>type</span> <span>StringNumberMap</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> stringNumberMap<span>&gt;</span><span>;</span>
<span>// type StringNumberMap = Map&lt;string, number&gt;</span></code></pre><h2><a href="https://zod.dev/?id=sets"><span>Sets</span></a></h2><pre><code><span>const</span> numberSet <span>=</span> z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>type</span> <span>NumberSet</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> numberSet<span>&gt;</span><span>;</span>
<span>// type NumberSet = Set&lt;number&gt;</span></code></pre><p>Set schemas can be further constrained with the following utility methods.</p><pre><code>z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>)</span><span>;</span> <span>// must contain at least one item</span>
z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or more items</span>
z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or fewer items</span>
z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>size</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 items exactly</span></code></pre><h2><a href="https://zod.dev/?id=intersections"><span>Intersections</span></a></h2><p>Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.</p><pre><code><span>const</span> Person <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> Employee <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  role<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> EmployedPerson <span>=</span> z<span>.</span><span>intersection</span><span>(</span>Person<span>,</span> Employee<span>)</span><span>;</span>

<span>// equivalent to:</span>
<span>const</span> EmployedPerson <span>=</span> Person<span>.</span><span>and</span><span>(</span>Employee<span>)</span><span>;</span></code></pre><p>Though in many cases, it is recommended to use <code>A.merge(B)</code> to merge two objects. The <code>.merge</code> method returns a new <code>ZodObject</code> instance, whereas <code>A.and(B)</code> returns a less useful <code>ZodIntersection</code> instance that lacks common object methods like <code>pick</code> and <code>omit</code>.</p><pre><code><span>const</span> a <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> b <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>boolean</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> c <span>=</span> z<span>.</span><span>intersection</span><span>(</span>a<span>,</span> b<span>)</span><span>;</span>

<span>type</span> <span>c</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> c<span>&gt;</span><span>;</span> <span>// =&gt; number</span></code></pre>



<h2><a href="https://zod.dev/?id=recursive-types"><span>Recursive types</span></a></h2><p>You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".</p><pre><code><span>const</span> baseCategorySchema <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>Category</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> baseCategorySchema<span>&gt;</span> <span>&amp;</span> <span>{</span>
  subcategories<span>:</span> Category<span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>const</span> categorySchema<span>:</span> z<span>.</span>ZodType<span>&lt;</span>Category<span>&gt;</span> <span>=</span> baseCategorySchema<span>.</span><span>extend</span><span>(</span><span>{</span>
  subcategories<span>:</span> z<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> categorySchema<span>.</span><span>array</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

categorySchema<span>.</span><span>parse</span><span>(</span><span>{</span>
  name<span>:</span> <span>"People"</span><span>,</span>
  subcategories<span>:</span> <span>[</span>
    <span>{</span>
      name<span>:</span> <span>"Politicians"</span><span>,</span>
      subcategories<span>:</span> <span>[</span>
        <span>{</span>
          name<span>:</span> <span>"Presidents"</span><span>,</span>
          subcategories<span>:</span> <span>[</span><span>]</span><span>,</span>
        <span>}</span><span>,</span>
      <span>]</span><span>,</span>
    <span>}</span><span>,</span>
  <span>]</span><span>,</span>
<span>}</span><span>)</span><span>;</span> <span>// passes</span></code></pre><p>Thanks to <a href="https://github.com/crasite">crasite</a> for this example.</p><h3><a href="https://zod.dev/?id=zodtype-with-zodeffects"><span>ZodType with ZodEffects</span></a></h3><p>When using <code>z.ZodType</code> with <code>z.ZodEffects</code> (
<a href="https://github.com/colinhacks/zod#refine"><code>.refine</code></a>,
<a href="https://github.com/colinhacks/zod#transform"><code>.transform</code></a>,
<a href="https://github.com/colinhacks/zod#preprocess"><code>preprocess</code></a>,
etc...
), you will need to define the input and output types of the schema. <code>z.ZodType&lt;Output, z.ZodTypeDef, Input&gt;</code></p><pre><code><span>const</span> isValidId <span>=</span> <span>(</span>id<span>:</span> <span>string</span><span>)</span><span>:</span> id <span>is</span> <span><span>`</span><span><span>${</span><span>string</span><span>}</span></span><span>/</span><span><span>${</span><span>string</span><span>}</span></span><span>`</span></span> <span>=&gt;</span>
  id<span>.</span><span>split</span><span>(</span><span>"/"</span><span>)</span><span>.</span>length <span>===</span> <span>2</span><span>;</span>

<span>const</span> baseSchema <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  id<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span>isValidId<span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>Input</span> <span>=</span> z<span>.</span>input<span>&lt;</span><span>typeof</span> baseSchema<span>&gt;</span> <span>&amp;</span> <span>{</span>
  children<span>:</span> Input<span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>type</span> <span>Output</span> <span>=</span> z<span>.</span>output<span>&lt;</span><span>typeof</span> baseSchema<span>&gt;</span> <span>&amp;</span> <span>{</span>
  children<span>:</span> Output<span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>const</span> schema<span>:</span> z<span>.</span>ZodType<span>&lt;</span>Output<span>,</span> z<span>.</span>ZodTypeDef<span>,</span> Input<span>&gt;</span> <span>=</span> baseSchema<span>.</span><span>extend</span><span>(</span><span>{</span>
  children<span>:</span> z<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> schema<span>.</span><span>array</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>Thanks to <a href="https://github.com/marcus13371337">marcus13371337</a> and <a href="https://github.com/JoelBeeldi">JoelBeeldi</a> for this example.</p><h3><a href="https://zod.dev/?id=json-type"><span>JSON type</span></a></h3><p>If you want to validate any JSON value, you can use the snippet below.</p><pre><code><span>const</span> literalSchema <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>boolean</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>null</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>type</span> <span>Literal</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> literalSchema<span>&gt;</span><span>;</span>
<span>type</span> <span>Json</span> <span>=</span> Literal <span>|</span> <span>{</span> <span>[</span>key<span>:</span> <span>string</span><span>]</span><span>:</span> Json <span>}</span> <span>|</span> Json<span>[</span><span>]</span><span>;</span>
<span>const</span> jsonSchema<span>:</span> z<span>.</span>ZodType<span>&lt;</span>Json<span>&gt;</span> <span>=</span> z<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span>
  z<span>.</span><span>union</span><span>(</span><span>[</span>literalSchema<span>,</span> z<span>.</span><span>array</span><span>(</span>jsonSchema<span>)</span><span>,</span> z<span>.</span><span>record</span><span>(</span>jsonSchema<span>)</span><span>]</span><span>)</span>
<span>)</span><span>;</span>

jsonSchema<span>.</span><span>parse</span><span>(</span>data<span>)</span><span>;</span></code></pre><p>Thanks to <a href="https://github.com/ggoodman">ggoodman</a> for suggesting this.</p><h3><a href="https://zod.dev/?id=cyclical-objects"><span>Cyclical objects</span></a></h3><p>Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop in some cases.</p><blockquote>
<p>To detect cyclical objects before they cause problems, consider <a href="https://gist.github.com/colinhacks/d35825e505e635df27cc950776c5500b">this approach</a>.</p></blockquote>
<h2><a href="https://zod.dev/?id=promises"><span>Promises</span></a></h2><pre><code><span>const</span> numberPromise <span>=</span> z<span>.</span><span>promise</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><p>"Parsing" works a little differently with promise schemas. Validation happens in two parts:</p><ol><li>Zod synchronously checks that the input is an instance of Promise (i.e. an object with <code>.then</code> and <code>.catch</code> methods.).</li><li>Zod uses <code>.then</code> to attach an additional validation step onto the existing Promise. You'll have to use <code>.catch</code> on the returned Promise to handle validation failures.</li></ol><pre><code>numberPromise<span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>
<span>// ZodError: Non-Promise type: string</span>

numberPromise<span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>"tuna"</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; Promise&lt;number&gt;</span>

<span>const</span> <span>test</span> <span>=</span> <span>async</span> <span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>await</span> numberPromise<span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>"tuna"</span><span>)</span><span>)</span><span>;</span>
  <span>// ZodError: Non-number type: string</span>

  <span>await</span> numberPromise<span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3.14</span><span>)</span><span>)</span><span>;</span>
  <span>// =&gt; 3.14</span>
<span>}</span><span>;</span></code></pre>

<h2><a href="https://zod.dev/?id=instanceof"><span>Instanceof</span></a></h2><p>You can use <code>z.instanceof</code> to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.</p><pre><code><span>class</span> <span>Test</span> <span>{</span>
  name<span>:</span> <span>string</span><span>;</span>
<span>}</span>

<span>const</span> TestSchema <span>=</span> z<span>.</span><span>instanceof</span><span>(</span>Test<span>)</span><span>;</span>

<span>const</span> blob<span>:</span> <span>any</span> <span>=</span> <span>"whatever"</span><span>;</span>
TestSchema<span>.</span><span>parse</span><span>(</span><span>new</span> <span>Test</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// passes</span>
TestSchema<span>.</span><span>parse</span><span>(</span>blob<span>)</span><span>;</span> <span>// throws</span></code></pre><h2><a href="https://zod.dev/?id=functions"><span>Functions</span></a></h2><p>Zod also lets you define "function schemas". This makes it easy to validate the inputs and outputs of a function without intermixing your validation code and "business logic".</p><p>You can create a function schema with <code>z.function(args, returnType)</code> .</p><pre><code><span>const</span> myFunction <span>=</span> z<span>.</span><span>function</span><span>(</span><span>)</span><span>;</span>

<span>type</span> <span>myFunction</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> myFunction<span>&gt;</span><span>;</span>
<span>// =&gt; ()=&gt;unknown</span></code></pre><p>Define inputs and outputs.</p><pre><code><span>const</span> myFunction <span>=</span> z
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span> <span>// accepts an arbitrary number of arguments</span>
  <span>.</span><span>returns</span><span>(</span>z<span>.</span><span>boolean</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>type</span> <span>myFunction</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> myFunction<span>&gt;</span><span>;</span>
<span>// =&gt; (arg0: string, arg1: number)=&gt;boolean</span></code></pre>

<p>Function schemas have an <code>.implement()</code> method which accepts a function and returns a new function that automatically validates its inputs and outputs.</p><pre><code><span>const</span> trimmedLength <span>=</span> z
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span> <span>// accepts an arbitrary number of arguments</span>
  <span>.</span><span>returns</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>implement</span><span>(</span><span>(</span>x<span>)</span> <span>=&gt;</span> <span>{</span>
    <span>// TypeScript knows x is a string!</span>
    <span>return</span> x<span>.</span><span>trim</span><span>(</span><span>)</span><span>.</span>length<span>;</span>
  <span>}</span><span>)</span><span>;</span>

<span>trimmedLength</span><span>(</span><span>"sandwich"</span><span>)</span><span>;</span> <span>// =&gt; 8</span>
<span>trimmedLength</span><span>(</span><span>" asdf "</span><span>)</span><span>;</span> <span>// =&gt; 4</span></code></pre><p>If you only care about validating inputs, just don't call the <code>.returns()</code> method. The output type will be inferred from the implementation.</p><blockquote>
<p>You can use the special <code>z.void()</code> option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)</p></blockquote>
<pre><code><span>const</span> myFunction <span>=</span> z
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>implement</span><span>(</span><span>(</span>arg<span>)</span> <span>=&gt;</span> <span>{</span>
    <span>return</span> <span>[</span>arg<span>.</span>length<span>]</span><span>;</span>
  <span>}</span><span>)</span><span>;</span>

myFunction<span>;</span> <span>// (arg: string)=&gt;number[]</span></code></pre><p>Extract the input and output schemas from a function schema.</p><pre><code>myFunction<span>.</span><span>parameters</span><span>(</span><span>)</span><span>;</span>
<span>// =&gt; ZodTuple&lt;[ZodString, ZodNumber]&gt;</span>

myFunction<span>.</span><span>returnType</span><span>(</span><span>)</span><span>;</span>
<span>// =&gt; ZodBoolean</span></code></pre>

<h2><a href="https://zod.dev/?id=preprocess"><span>Preprocess</span></a></h2><blockquote>
<p>Zod now supports primitive coercion without the need for <code>.preprocess()</code>. See the <a href="https://zod.dev/?id=coercion-for-primitives">coercion docs</a> for more information.</p></blockquote>
<p>Typically Zod operates under a "parse then transform" paradigm. Zod validates the input first, then passes it through a chain of transformation functions. (For more information about transforms, read the <a href="https://zod.dev/?id=transform">.transform docs</a>.)</p><p>But sometimes you want to apply some transform to the input <em>before</em> parsing happens. A common use case: type coercion. Zod enables this with the <code>z.preprocess()</code>.</p><pre><code><span>const</span> castToString <span>=</span> z<span>.</span><span>preprocess</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> <span>String</span><span>(</span>val<span>)</span><span>,</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><p>This returns a <code>ZodEffects</code> instance. <code>ZodEffects</code> is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.</p><h2><a href="https://zod.dev/?id=custom-schemas"><span>Custom schemas</span></a></h2><p>You can create a Zod schema for any TypeScript type by using <code>z.custom()</code>. This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.</p><pre><code><span>const</span> px <span>=</span> z<span>.</span><span><span>custom</span><span><span>&lt;</span><span><span>`</span><span><span>${</span><span>number</span><span>}</span></span><span>px</span><span>`</span></span><span>&gt;</span></span></span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> <span>{</span>
  <span>return</span> <span>typeof</span> val <span>===</span> <span>"string"</span> <span>?</span> <span><span>/</span><span>^\d+px$</span><span>/</span></span><span>.</span><span>test</span><span>(</span>val<span>)</span> <span>:</span> <span>false</span><span>;</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>px</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> px<span>&gt;</span><span>;</span> <span>// `${number}px`</span>

px<span>.</span><span>parse</span><span>(</span><span>"42px"</span><span>)</span><span>;</span> <span>// "42px"</span>
px<span>.</span><span>parse</span><span>(</span><span>"42vw"</span><span>)</span><span>;</span> <span>// throws;</span></code></pre><p>If you don't provide a validation function, Zod will allow any value. This can be dangerous!</p><pre><code>z<span>.</span><span><span>custom</span><span><span>&lt;</span><span>{</span> arg<span>:</span> <span>string</span> <span>}</span><span>&gt;</span></span></span><span>(</span><span>)</span><span>;</span> <span>// performs no validation</span></code></pre><p>You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of <a href="https://zod.dev/?id=refine"><code>.refine</code></a>.</p><pre><code>z<span>.</span><span><span>custom</span><span><span>&lt;</span><span>...</span><span>&gt;</span></span></span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> <span>...</span><span>,</span> <span>"custom error message"</span><span>)</span><span>;</span></code></pre><h2><a href="https://zod.dev/?id=schema-methods"><span>Schema methods</span></a></h2><p>All Zod schemas contain certain methods.</p><h3><a href="https://zod.dev/?id=parse"><span><code>.parse</code></span></a></h3><p><code>.parse(data: unknown): T</code></p><p>Given any Zod schema, you can call its <code>.parse</code> method to check <code>data</code> is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.</p><blockquote>
<p>IMPORTANT: The value returned by <code>.parse</code> is a <em>deep clone</em> of the variable you passed in.</p></blockquote>
<pre><code><span>const</span> stringSchema <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>

stringSchema<span>.</span><span>parse</span><span>(</span><span>"fish"</span><span>)</span><span>;</span> <span>// =&gt; returns "fish"</span>
stringSchema<span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// throws error</span></code></pre><h3><a href="https://zod.dev/?id=parseasync"><span><code>.parseAsync</code></span></a></h3><p><code>.parseAsync(data:unknown): Promise&lt;T&gt;</code></p><p>If you use asynchronous <a href="https://zod.dev/?id=refine">refinements</a> or <a href="https://zod.dev/?id=transform">transforms</a> (more on those later), you'll need to use <code>.parseAsync</code>.</p><pre><code><span>const</span> stringSchema <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>async</span> <span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length <span>&lt;=</span> <span>8</span><span>)</span><span>;</span>

<span>await</span> stringSchema<span>.</span><span>parseAsync</span><span>(</span><span>"hello"</span><span>)</span><span>;</span> <span>// =&gt; returns "hello"</span>
<span>await</span> stringSchema<span>.</span><span>parseAsync</span><span>(</span><span>"hello world"</span><span>)</span><span>;</span> <span>// =&gt; throws error</span></code></pre><h3><a href="https://zod.dev/?id=safeparse"><span><code>.safeParse</code></span></a></h3><p><code>.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }</code></p><p>If you don't want Zod to throw errors when validation fails, use <code>.safeParse</code>. This method returns an object containing either the successfully parsed data or a ZodError instance containing detailed information about the validation problems.</p><pre><code>stringSchema<span>.</span><span>safeParse</span><span>(</span><span>12</span><span>)</span><span>;</span>
<span>// =&gt; { success: false; error: ZodError }</span>

stringSchema<span>.</span><span>safeParse</span><span>(</span><span>"billie"</span><span>)</span><span>;</span>
<span>// =&gt; { success: true; data: 'billie' }</span></code></pre><p>The result is a <em>discriminated union</em>, so you can handle errors very conveniently:</p><pre><code><span>const</span> result <span>=</span> stringSchema<span>.</span><span>safeParse</span><span>(</span><span>"billie"</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>!</span>result<span>.</span>success<span>)</span> <span>{</span>
  <span>// handle error then return</span>
  result<span>.</span>error<span>;</span>
<span>}</span> <span>else</span> <span>{</span>
  <span>// do something</span>
  result<span>.</span>data<span>;</span>
<span>}</span></code></pre><h3><a href="https://zod.dev/?id=safeparseasync"><span><code>.safeParseAsync</code></span></a></h3><blockquote>
<p>Alias: <code>.spa</code></p></blockquote>
<p>An asynchronous version of <code>safeParse</code>.</p><pre><code><span>await</span> stringSchema<span>.</span><span>safeParseAsync</span><span>(</span><span>"billie"</span><span>)</span><span>;</span></code></pre><p>For convenience, this has been aliased to <code>.spa</code>:</p><pre><code><span>await</span> stringSchema<span>.</span><span>spa</span><span>(</span><span>"billie"</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=refine"><span><code>.refine</code></span></a></h3><p><code>.refine(validator: (data:T)=&gt;any, params?: RefineParams)</code></p><p>Zod lets you provide custom validation logic via <em>refinements</em>. (For advanced features like creating multiple issues and customizing error codes, see <a href="https://zod.dev/?id=superrefine"><code>.superRefine</code></a>.)</p><p>Zod was designed to mirror TypeScript as closely as possible. But there are many so-called "refinement types" you may wish to check for that can't be represented in TypeScript's type system. For instance: checking that a number is an integer or that a string is a valid email address.</p><p>For example, you can define a custom validation check on <em>any</em> Zod schema with <code>.refine</code> :</p><pre><code><span>const</span> myString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length <span>&lt;=</span> <span>255</span><span>,</span> <span>{</span>
  message<span>:</span> <span>"String can't be more than 255 characters"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></code></pre><blockquote>
<p>⚠️ Refinement functions should not throw. Instead they should return a falsy value to signal failure.</p></blockquote>
<h4><a href="https://zod.dev/?id=arguments"><span>Arguments</span></a></h4><p>As you can see, <code>.refine</code> takes two arguments.</p><ol><li>The first is the validation function. This function takes one input (of type <code>T</code> — the inferred type of the schema) and returns <code>any</code>. Any truthy value will pass validation. (Prior to <a href="mailto:zod@1.6.2">zod@1.6.2</a> the validation function had to return a boolean.)</li><li>The second argument accepts some options. You can use this to customize certain error-handling behavior:</li></ol><pre><code><span>type</span> <span>RefineParams</span> <span>=</span> <span>{</span>
  <span>// override error message</span>
  message<span>?</span><span>:</span> <span>string</span><span>;</span>

  <span>// appended to error path</span>
  path<span>?</span><span>:</span> <span>(</span><span>string</span> <span>|</span> <span>number</span><span>)</span><span>[</span><span>]</span><span>;</span>

  <span>// params object you can use to customize message</span>
  <span>// in error map</span>
  params<span>?</span><span>:</span> object<span>;</span>
<span>}</span><span>;</span></code></pre><p>For advanced cases, the second argument can also be a function that returns <code>RefineParams</code>.</p><pre><code><span>const</span> longString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span>
  <span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length <span>&gt;</span> <span>10</span><span>,</span>
  <span>(</span>val<span>)</span> <span>=&gt;</span> <span>(</span><span>{</span> message<span>:</span> <span><span>`</span><span><span>${</span>val<span>}</span></span><span> is not more than 10 characters</span><span>`</span></span> <span>}</span><span>)</span>
<span>)</span><span>;</span></code></pre><h4><a href="https://zod.dev/?id=customize-error-path"><span>Customize error path</span></a></h4><pre><code><span>const</span> passwordForm <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    password<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    confirm<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span>data<span>)</span> <span>=&gt;</span> data<span>.</span>password <span>===</span> data<span>.</span>confirm<span>,</span> <span>{</span>
    message<span>:</span> <span>"Passwords don't match"</span><span>,</span>
    path<span>:</span> <span>[</span><span>"confirm"</span><span>]</span><span>,</span> <span>// path of error</span>
  <span>}</span><span>)</span><span>;</span>

passwordForm<span>.</span><span>parse</span><span>(</span><span>{</span> password<span>:</span> <span>"asdf"</span><span>,</span> confirm<span>:</span> <span>"qwer"</span> <span>}</span><span>)</span><span>;</span></code></pre><p>Because you provided a <code>path</code> parameter, the resulting error will be:</p><pre><code>ZodError <span>{</span>
  issues<span>:</span> <span>[</span><span>{</span>
    <span>"code"</span><span>:</span> <span>"custom"</span><span>,</span>
    <span>"path"</span><span>:</span> <span>[</span> <span>"confirm"</span> <span>]</span><span>,</span>
    <span>"message"</span><span>:</span> <span>"Passwords don't match"</span>
  <span>}</span><span>]</span>
<span>}</span></code></pre><h4><a href="https://zod.dev/?id=asynchronous-refinements"><span>Asynchronous refinements</span></a></h4><p>Refinements can also be async:</p><pre><code><span>const</span> userId <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>async</span> <span>(</span>id<span>)</span> <span>=&gt;</span> <span>{</span>
  <span>// verify that ID exists in database</span>
  <span>return</span> <span>true</span><span>;</span>
<span>}</span><span>)</span><span>;</span></code></pre><blockquote>
<p>⚠️ If you use async refinements, you must use the <code>.parseAsync</code> method to parse data! Otherwise Zod will throw an error.</p></blockquote>
<h4><a href="https://zod.dev/?id=relationship-to-transforms"><span>Relationship to transforms</span></a></h4><p>Transforms and refinements can be interleaved:</p><pre><code>z<span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length<span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val <span>&gt;</span> <span>25</span><span>)</span><span>;</span></code></pre>

<h3><a href="https://zod.dev/?id=superrefine"><span><code>.superRefine</code></span></a></h3><p>The <code>.refine</code> method is actually syntactic sugar atop a more versatile (and verbose) method called <code>superRefine</code>. Here's an example:</p><pre><code><span>const</span> Strings <span>=</span> z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>superRefine</span><span>(</span><span>(</span>val<span>,</span> ctx<span>)</span> <span>=&gt;</span> <span>{</span>
  <span>if</span> <span>(</span>val<span>.</span>length <span>&gt;</span> <span>3</span><span>)</span> <span>{</span>
    ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
      code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>too_big<span>,</span>
      maximum<span>:</span> <span>3</span><span>,</span>
      type<span>:</span> <span>"array"</span><span>,</span>
      inclusive<span>:</span> <span>true</span><span>,</span>
      message<span>:</span> <span>"Too many items 😡"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>

  <span>if</span> <span>(</span>val<span>.</span>length <span>!==</span> <span>new</span> <span>Set</span><span>(</span>val<span>)</span><span>.</span>size<span>)</span> <span>{</span>
    ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
      code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>custom<span>,</span>
      message<span>:</span> <span><span>`</span><span>No duplicates allowed.</span><span>`</span></span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>
<span>}</span><span>)</span><span>;</span></code></pre><p>You can add as many issues as you like. If <code>ctx.addIssue</code> is <em>not</em> called during the execution of the function, validation passes.</p><p>Normally refinements always create issues with a <code>ZodIssueCode.custom</code> error code, but with <code>superRefine</code> it's possible to throw issues of any <code>ZodIssueCode</code>. Each issue code is described in detail in the Error Handling guide: <a href="https://zod.dev/ERROR_HANDLING">ERROR_HANDLING.md</a>.</p><h4><a href="https://zod.dev/?id=abort-early"><span>Abort early</span></a></h4><p>By default, parsing will continue even after a refinement check fails. For instance, if you chain together multiple refinements, they will all be executed. However, it may be desirable to <em>abort early</em> to prevent later refinements from being executed. To achieve this, pass the <code>fatal</code> flag to <code>ctx.addIssue</code> and return <code>z.NEVER</code>.</p><pre><code><span>const</span> schema <span>=</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>superRefine</span><span>(</span><span>(</span>val<span>,</span> ctx<span>)</span> <span>=&gt;</span> <span>{</span>
  <span>if</span> <span>(</span>val <span>&lt;</span> <span>10</span><span>)</span> <span>{</span>
    ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
      code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>custom<span>,</span>
      message<span>:</span> <span>"should be &gt;= 10"</span><span>,</span>
      fatal<span>:</span> <span>true</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>

    <span>return</span> z<span>.</span><span>NEVER</span><span>;</span>
  <span>}</span>

  <span>if</span> <span>(</span>val <span>!==</span> <span>12</span><span>)</span> <span>{</span>
    ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
      code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>custom<span>,</span>
      message<span>:</span> <span>"should be twelve"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>
<span>}</span><span>)</span><span>;</span></code></pre><h4><a href="https://zod.dev/?id=type-refinements"><span>Type refinements</span></a></h4><p>If you provide a <a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates">type predicate</a> to <code>.refine()</code> or <code>.superRefine()</code>, the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:</p><pre><code><span>const</span> schema <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    first<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    second<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>nullable</span><span>(</span><span>)</span>
  <span>.</span><span>superRefine</span><span>(</span><span>(</span>arg<span>,</span> ctx<span>)</span><span>:</span> arg <span>is</span> <span>{</span> first<span>:</span> <span>string</span><span>;</span> second<span>:</span> <span>number</span> <span>}</span> <span>=&gt;</span> <span>{</span>
    <span>if</span> <span>(</span><span>!</span>arg<span>)</span> <span>{</span>
      ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
        code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>custom<span>,</span> <span>// customize your issue</span>
        message<span>:</span> <span>"object should exist"</span><span>,</span>
      <span>}</span><span>)</span><span>;</span>
    <span>}</span>

    <span>return</span> z<span>.</span><span>NEVER</span><span>;</span> <span>// The return value is not used, but we need to return something to satisfy the typing</span>
  <span>}</span><span>)</span>
  <span>// here, TS knows that arg is not null</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span>arg<span>)</span> <span>=&gt;</span> arg<span>.</span>first <span>===</span> <span>"bob"</span><span>,</span> <span>"`first` is not `bob`!"</span><span>)</span><span>;</span></code></pre><blockquote>
<p>⚠️ You <strong>must</strong> use <code>ctx.addIssue()</code> instead of returning a boolean value to indicate whether the validation passes. If <code>ctx.addIssue</code> is <em>not</em> called during the execution of the function, validation passes.</p></blockquote>
<h3><a href="https://zod.dev/?id=transform"><span><code>.transform</code></span></a></h3><p>To transform data after parsing, use the <code>transform</code> method.</p><pre><code><span>const</span> stringToNumber <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length<span>)</span><span>;</span>

stringToNumber<span>.</span><span>parse</span><span>(</span><span>"string"</span><span>)</span><span>;</span> <span>// =&gt; 6</span></code></pre><h4><a href="https://zod.dev/?id=chaining-order"><span>Chaining order</span></a></h4><p>Note that <code>stringToNumber</code> above is an instance of the <code>ZodEffects</code> subclass. It is NOT an instance of <code>ZodString</code>. If you want to use the built-in methods of <code>ZodString</code> (e.g. <code>.email()</code>) you must apply those methods <em>before</em> any transforms.</p><pre><code><span>const</span> emailToDomain <span>=</span> z
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>email</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span><span>split</span><span>(</span><span>"@"</span><span>)</span><span>[</span><span>1</span><span>]</span><span>)</span><span>;</span>

emailToDomain<span>.</span><span>parse</span><span>(</span><span>"colinhacks@example.com"</span><span>)</span><span>;</span> <span>// =&gt; example.com</span></code></pre><h4><a href="https://zod.dev/?id=validating-during-transform"><span>Validating during transform</span></a></h4><p>The <code>.transform</code> method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining <code>transform</code> and <code>refine</code>.</p><p>As with <code>.superRefine</code>, the transform function receives a <code>ctx</code> object with an <code>addIssue</code> method that can be used to register validation issues.</p><pre><code><span>const</span> numberInString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span>val<span>,</span> ctx<span>)</span> <span>=&gt;</span> <span>{</span>
  <span>const</span> parsed <span>=</span> <span>parseInt</span><span>(</span>val<span>)</span><span>;</span>
  <span>if</span> <span>(</span><span>isNaN</span><span>(</span>parsed<span>)</span><span>)</span> <span>{</span>
    ctx<span>.</span><span>addIssue</span><span>(</span><span>{</span>
      code<span>:</span> z<span>.</span>ZodIssueCode<span>.</span>custom<span>,</span>
      message<span>:</span> <span>"Not a number"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>

    <span>// This is a special symbol you can use to</span>
    <span>// return early from the transform function.</span>
    <span>// It has type `never` so it does not affect the</span>
    <span>// inferred return type.</span>
    <span>return</span> z<span>.</span><span>NEVER</span><span>;</span>
  <span>}</span>
  <span>return</span> parsed<span>;</span>
<span>}</span><span>)</span><span>;</span></code></pre><h4><a href="https://zod.dev/?id=relationship-to-refinements"><span>Relationship to refinements</span></a></h4><p>Transforms and refinements can be interleaved. These will be executed in the order they are declared.</p><pre><code><span>const</span> nameToGreeting <span>=</span> z
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span><span>toUpperCase</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length <span>&gt;</span> <span>15</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> <span><span>`</span><span>Hello </span><span><span>${</span>val<span>}</span></span><span>`</span></span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span><span>indexOf</span><span>(</span><span>"!"</span><span>)</span> <span>===</span> <span>-</span><span>1</span><span>)</span><span>;</span></code></pre><h4><a href="https://zod.dev/?id=async-transforms"><span>Async transforms</span></a></h4><p>Transforms can also be async.</p><pre><code><span>const</span> IdToUser <span>=</span> z
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>uuid</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>async</span> <span>(</span>id<span>)</span> <span>=&gt;</span> <span>{</span>
    <span>return</span> <span>await</span> <span>getUserById</span><span>(</span>id<span>)</span><span>;</span>
  <span>}</span><span>)</span><span>;</span></code></pre><blockquote>
<p>⚠️ If your schema contains asynchronous transforms, you must use .parseAsync() or .safeParseAsync() to parse data. Otherwise Zod will throw an error.</p></blockquote>
<h3><a href="https://zod.dev/?id=default"><span><code>.default</code></span></a></h3><p>You can use transforms to implement the concept of "default values" in Zod.</p><pre><code><span>const</span> stringWithDefault <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>default</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>

stringWithDefault<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span></code></pre><p>Optionally, you can pass a function into <code>.default</code> that will be re-executed whenever a default value needs to be generated:</p><pre><code><span>const</span> numberWithRandomDefault <span>=</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>default</span><span>(</span>Math<span>.</span>random<span>)</span><span>;</span>

numberWithRandomDefault<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.4413456736055323</span>
numberWithRandomDefault<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.1871840107401901</span>
numberWithRandomDefault<span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.7223408162401552</span></code></pre><p>Conceptually, this is how Zod processes default values:</p><ol><li>If the input is <code>undefined</code>, the default value is returned</li><li>Otherwise, the data is parsed using the base schema</li></ol><h3><a href="https://zod.dev/?id=describe"><span><code>.describe</code></span></a></h3><p>Use <code>.describe()</code> to add a <code>description</code> property to the resulting schema.</p><pre><code><span>const</span> documentedString <span>=</span> z
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>describe</span><span>(</span><span>"A useful bit of text, if you know what to do with it."</span><span>)</span><span>;</span>
documentedString<span>.</span>description<span>;</span> <span>// A useful bit of text…</span></code></pre><p>This can be useful for documenting a field, for example in a JSON Schema using a library like <a href="https://github.com/StefanTerdell/zod-to-json-schema"><code>zod-to-json-schema</code></a>).</p><h3><a href="https://zod.dev/?id=catch"><span><code>.catch</code></span></a></h3><p>Use <code>.catch()</code> to provide a "catch value" to be returned in the event of a parsing error.</p><pre><code><span>const</span> numberWithCatch <span>=</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>catch</span><span>(</span><span>42</span><span>)</span><span>;</span>

numberWithCatch<span>.</span><span>parse</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// =&gt; 5</span>
numberWithCatch<span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; 42</span></code></pre><p>Optionally, you can pass a function into <code>.catch</code> that will be re-executed whenever a default value needs to be generated. A <code>ctx</code> object containing the caught error will be passed into this function.</p><pre><code><span>const</span> numberWithRandomCatch <span>=</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>catch</span><span>(</span><span>(</span>ctx<span>)</span> <span>=&gt;</span> <span>{</span>
  ctx<span>.</span>error<span>;</span> <span>// the caught ZodError</span>
  <span>return</span> Math<span>.</span><span>random</span><span>(</span><span>)</span><span>;</span>
<span>}</span><span>)</span><span>;</span>

numberWithRandomCatch<span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.4413456736055323</span>
numberWithRandomCatch<span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.1871840107401901</span>
numberWithRandomCatch<span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.7223408162401552</span></code></pre><p>Conceptually, this is how Zod processes "catch values":</p><ol><li>The data is parsed using the base schema</li><li>If the parsing fails, the "catch value" is returned</li></ol><h3><a href="https://zod.dev/?id=optional"><span><code>.optional</code></span></a></h3><p>A convenience method that returns an optional version of a schema.</p><pre><code><span>const</span> optionalString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span> <span>// string | undefined</span>

<span>// equivalent to</span>
z<span>.</span><span>optional</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=nullable"><span><code>.nullable</code></span></a></h3><p>A convenience method that returns a nullable version of a schema.</p><pre><code><span>const</span> nullableString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span> <span>// string | null</span>

<span>// equivalent to</span>
z<span>.</span><span>nullable</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=nullish"><span><code>.nullish</code></span></a></h3><p>A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both <code>undefined</code> and <code>null</code>. Read more about the concept of "nullish" <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing">in the TypeScript 3.7 release notes</a>.</p><pre><code><span>const</span> nullishString <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullish</span><span>(</span><span>)</span><span>;</span> <span>// string | null | undefined</span>

<span>// equivalent to</span>
z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=array"><span><code>.array</code></span></a></h3><p>A convenience method that returns an array schema for the given type:</p><pre><code><span>const</span> stringArray <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span> <span>// string[]</span>

<span>// equivalent to</span>
z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=promise"><span><code>.promise</code></span></a></h3><p>A convenience method for promise types:</p><pre><code><span>const</span> stringPromise <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>promise</span><span>(</span><span>)</span><span>;</span> <span>// Promise&lt;string&gt;</span>

<span>// equivalent to</span>
z<span>.</span><span>promise</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=or"><span><code>.or</code></span></a></h3><p>A convenience method for <a href="https://zod.dev/?id=unions">union types</a>.</p><pre><code><span>const</span> stringOrNumber <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// string | number</span>

<span>// equivalent to</span>
z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=and"><span><code>.and</code></span></a></h3><p>A convenience method for creating intersection types.</p><pre><code><span>const</span> nameAndAge <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span>
  <span>.</span><span>and</span><span>(</span>z<span>.</span><span>object</span><span>(</span><span>{</span> age<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>;</span> <span>// { name: string } &amp; { age: number }</span>

<span>// equivalent to</span>
z<span>.</span><span>intersection</span><span>(</span>z<span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>,</span> z<span>.</span><span>object</span><span>(</span><span>{</span> age<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>;</span></code></pre><h3><a href="https://zod.dev/?id=brand"><span><code>.brand</code></span></a></h3><p><code>.brand&lt;T&gt;() =&gt; ZodBranded&lt;this, B&gt;</code></p><p>TypeScript's type system is structural, which means that any two types that are structurally equivalent are considered the same.</p><pre><code><span>type</span> <span>Cat</span> <span>=</span> <span>{</span> name<span>:</span> <span>string</span> <span>}</span><span>;</span>
<span>type</span> <span>Dog</span> <span>=</span> <span>{</span> name<span>:</span> <span>string</span> <span>}</span><span>;</span>

<span>const</span> <span>petCat</span> <span>=</span> <span>(</span>cat<span>:</span> Cat<span>)</span> <span>=&gt;</span> <span>{</span><span>}</span><span>;</span>
<span>const</span> fido<span>:</span> Dog <span>=</span> <span>{</span> name<span>:</span> <span>"fido"</span> <span>}</span><span>;</span>
<span>petCat</span><span>(</span>fido<span>)</span><span>;</span> <span>// works fine</span></code></pre><p>In some cases, its can be desirable to simulate <em>nominal typing</em> inside TypeScript. For instance, you may wish to write a function that only accepts an input that has been validated by Zod. This can be achieved with <em>branded types</em> (AKA <em>opaque types</em>).</p><pre><code><span>const</span> Cat <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span><span>brand</span><span><span>&lt;</span><span>"Cat"</span><span>&gt;</span></span></span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>Cat</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> Cat<span>&gt;</span><span>;</span>

<span>const</span> <span>petCat</span> <span>=</span> <span>(</span>cat<span>:</span> Cat<span>)</span> <span>=&gt;</span> <span>{</span><span>}</span><span>;</span>

<span>// this works</span>
<span>const</span> simba <span>=</span> Cat<span>.</span><span>parse</span><span>(</span><span>{</span> name<span>:</span> <span>"simba"</span> <span>}</span><span>)</span><span>;</span>
<span>petCat</span><span>(</span>simba<span>)</span><span>;</span>

<span>// this doesn't</span>
<span>petCat</span><span>(</span><span>{</span> name<span>:</span> <span>"fido"</span> <span>}</span><span>)</span><span>;</span></code></pre><p>Under the hood, this works by attaching a "brand" to the inferred type using an intersection type. This way, plain/unbranded data structures are no longer assignable to the inferred type of the schema.</p><pre><code><span>const</span> Cat <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span><span>brand</span><span><span>&lt;</span><span>"Cat"</span><span>&gt;</span></span></span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>Cat</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> Cat<span>&gt;</span><span>;</span>
<span>// {name: string} &amp; {[symbol]: "Cat"}</span></code></pre><p>Note that branded types do not affect the runtime result of <code>.parse</code>. It is a static-only construct.</p><h3><a href="https://zod.dev/?id=readonly"><span><code>.readonly</code></span></a></h3><p><code>.readonly() =&gt; ZodReadonly&lt;this&gt;</code></p><p>This method returns a <code>ZodReadonly</code> schema instance that parses the input using the base schema, then calls <code>Object.freeze()</code> on the result. The inferred type is also marked as <code>readonly</code>.</p><pre><code><span>const</span> schema <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span> name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>schema</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> schema<span>&gt;</span><span>;</span>
<span>// Readonly&lt;{name: string}&gt;</span>

<span>const</span> result <span>=</span> schema<span>.</span><span>parse</span><span>(</span><span>{</span> name<span>:</span> <span>"fido"</span> <span>}</span><span>)</span><span>;</span>
result<span>.</span>name <span>=</span> <span>"simba"</span><span>;</span> <span>// error</span></code></pre><p>The inferred type uses TypeScript's built-in readonly types when relevant.</p><pre><code>z<span>.</span><span>array</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// readonly string[]</span>

z<span>.</span><span>tuple</span><span>(</span><span>[</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// readonly [string, number]</span>

z<span>.</span><span>map</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>date</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// ReadonlyMap&lt;string, Date&gt;</span>

z<span>.</span><span>set</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// ReadonlySet&lt;string&gt;</span></code></pre><h3><a href="https://zod.dev/?id=pipe"><span><code>.pipe</code></span></a></h3><p>Schemas can be chained into validation "pipelines". It's useful for easily validating the result after a <code>.transform()</code>:</p><pre><code>z<span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length<span>)</span>
  <span>.</span><span>pipe</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>)</span><span>;</span></code></pre><p>The <code>.pipe()</code> method returns a <code>ZodPipeline</code> instance.</p><h4><a href="https://zod.dev/?id=you-can-use-pipe-to-fix-common-issues-with-zcoerce"><span>You can use <code>.pipe()</code> to fix common issues with <code>z.coerce</code>.</span></a></h4><p>You can constrain the input to types that work well with your chosen coercion. Then use <code>.pipe()</code> to apply the coercion.</p><p>without constrained input:</p><pre><code><span>const</span> toDate <span>=</span> z<span>.</span>coerce<span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>

<span>// works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toDate<span>.</span><span>safeParse</span><span>(</span><span>"2023-01-01"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>

<span>// might not be what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toDate<span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span></code></pre><p>with constrained input:</p><pre><code><span>const</span> datelike <span>=</span> z<span>.</span><span>union</span><span>(</span><span>[</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> z<span>.</span><span>date</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> datelikeToDate <span>=</span> datelike<span>.</span><span>pipe</span><span>(</span>z<span>.</span>coerce<span>.</span><span>date</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// still works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span>datelikeToDate<span>.</span><span>safeParse</span><span>(</span><span>"2023-01-01"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>

<span>// more likely what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span>datelikeToDate<span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// false</span></code></pre><p>You can also use this technique to avoid coercions that throw uncaught errors.</p><p>without constrained input:</p><pre><code><span>const</span> toBigInt <span>=</span> z<span>.</span>coerce<span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span>

<span>// works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toBigInt<span>.</span><span>safeParse</span><span>(</span><span>"42"</span><span>)</span><span>)</span><span>;</span> <span>// true</span>

<span>// probably not what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toBigInt<span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>)</span><span>;</span> <span>// throws uncaught error</span></code></pre><p>with constrained input:</p><pre><code><span>const</span> toNumber <span>=</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>pipe</span><span>(</span>z<span>.</span>coerce<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>const</span> toBigInt <span>=</span> z<span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span>toNumber<span>)</span><span>.</span><span>pipe</span><span>(</span>z<span>.</span>coerce<span>.</span><span>bigint</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// still works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toBigInt<span>.</span><span>safeParse</span><span>(</span><span>"42"</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// true</span>

<span>// error handled by zod, more likely what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span>toBigInt<span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span>success<span>)</span><span>;</span> <span>// false</span></code></pre><h2><a href="https://zod.dev/?id=guides-and-concepts"><span>Guides and concepts</span></a></h2><h3><a href="https://zod.dev/?id=type-inference"><span>Type inference</span></a></h3><p>You can extract the TypeScript type of any schema with <code>z.infer&lt;typeof mySchema&gt;</code> .</p><pre><code><span>const</span> <span>A</span> <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span><span>A</span></span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> <span>A</span><span>&gt;</span><span>;</span> <span>// string</span>

<span>const</span> u<span>:</span> <span>A</span> <span>=</span> <span>12</span><span>;</span> <span>// TypeError</span>
<span>const</span> u<span>:</span> <span>A</span> <span>=</span> <span>"asdf"</span><span>;</span> <span>// compiles</span></code></pre><p><strong>What about transforms?</strong></p><p>In reality each Zod schema internally tracks <strong>two</strong> types: an input and an output. For most schemas (e.g. <code>z.string()</code>) these two are the same. But once you add transforms into the mix, these two values can diverge. For instance <code>z.string().transform(val =&gt; val.length)</code> has an input of <code>string</code> and an output of <code>number</code>.</p><p>You can separately extract the input and output types like so:</p><pre><code><span>const</span> stringToNumber <span>=</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span>val<span>)</span> <span>=&gt;</span> val<span>.</span>length<span>)</span><span>;</span>

<span>// ⚠️ Important: z.infer returns the OUTPUT type!</span>
<span>type</span> <span>input</span> <span>=</span> z<span>.</span>input<span>&lt;</span><span>typeof</span> stringToNumber<span>&gt;</span><span>;</span> <span>// string</span>
<span>type</span> <span>output</span> <span>=</span> z<span>.</span>output<span>&lt;</span><span>typeof</span> stringToNumber<span>&gt;</span><span>;</span> <span>// number</span>

<span>// equivalent to z.output!</span>
<span>type</span> <span>inferred</span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> stringToNumber<span>&gt;</span><span>;</span> <span>// number</span></code></pre><h3><a href="https://zod.dev/?id=writing-generic-functions"><span>Writing generic functions</span></a></h3><p>With TypeScript generics, you can write reusable functions that accept Zod schemas as parameters. This enables you to create custom validation logic, schema transformations, and more, while maintaining type safety and inference.</p><p>When attempting to write a function that accepts a Zod schema as an input, it's tempting to try something like this:</p><pre><code><span>function</span> <span><span>inferSchema</span><span><span>&lt;</span><span>T</span><span>&gt;</span></span></span><span>(</span>schema<span>:</span> z<span>.</span>ZodType<span>&lt;</span><span>T</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>return</span> schema<span>;</span>
<span>}</span></code></pre><p>This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of <code>schema</code> will be an instance of <code>ZodType</code>.</p><pre><code><span>inferSchema</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; ZodType&lt;string&gt;</span></code></pre><p>This approach loses type information, namely <em>which subclass</em> the input actually is (in this case, <code>ZodString</code>). That means you can't call any string-specific methods like <code>.min()</code> on the result of <code>inferSchema</code>.</p><p>A better approach is to infer <em>the schema as a whole</em> instead of merely its inferred type. You can do this with a utility type called <code>z.ZodTypeAny</code>.</p><pre><code><span>function</span> <span><span>inferSchema</span><span><span>&lt;</span><span>T</span> <span>extends</span> z<span>.</span>ZodTypeAny<span>&gt;</span></span></span><span>(</span>schema<span>:</span> <span>T</span><span>)</span> <span>{</span>
  <span>return</span> schema<span>;</span>
<span>}</span>

<span>inferSchema</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; ZodString</span></code></pre><blockquote>
<p><code>ZodTypeAny</code> is just a shorthand for <code>ZodType&lt;any, any, any&gt;</code>, a type that is broad enough to match any Zod schema.</p></blockquote>
<p>The Result is now fully and properly typed, and the type system can infer the specific subclass of the schema.</p><h4><a href="https://zod.dev/?id=inferring-the-inferred-type"><span>Inferring the inferred type</span></a></h4><p>If you follow the best practice of using <code>z.ZodTypeAny</code> as the generic parameter for your schema, you may encounter issues with the parsed data being typed as <code>any</code> instead of the inferred type of the schema.</p><pre><code><span>function</span> <span><span>parseData</span><span><span>&lt;</span><span>T</span> <span>extends</span> z<span>.</span>ZodTypeAny<span>&gt;</span></span></span><span>(</span>data<span>:</span> <span>unknown</span><span>,</span> schema<span>:</span> <span>T</span><span>)</span> <span>{</span>
  <span>return</span> schema<span>.</span><span>parse</span><span>(</span>data<span>)</span><span>;</span>
<span>}</span>

<span>parseData</span><span>(</span><span>"sup"</span><span>,</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; any</span></code></pre><p>Due to how TypeScript inference works, it is treating <code>schema</code> like a <code>ZodTypeAny</code> instead of the inferred type. You can fix this with a type cast using <code>z.infer</code>.</p><pre><code><span>function</span> <span><span>parseData</span><span><span>&lt;</span><span>T</span> <span>extends</span> z<span>.</span>ZodTypeAny<span>&gt;</span></span></span><span>(</span>data<span>:</span> <span>unknown</span><span>,</span> schema<span>:</span> <span>T</span><span>)</span> <span>{</span>
  <span>return</span> schema<span>.</span><span>parse</span><span>(</span>data<span>)</span> <span>as</span> z<span>.</span>infer<span>&lt;</span><span>T</span><span>&gt;</span><span>;</span>
  <span>//                        ^^^^^^^^^^^^^^ &lt;- add this</span>
<span>}</span>

<span>parseData</span><span>(</span><span>"sup"</span><span>,</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; string</span></code></pre><h4><a href="https://zod.dev/?id=constraining-allowable-inputs"><span>Constraining allowable inputs</span></a></h4><p>The <code>ZodType</code> class has three generic parameters.</p><pre><code><span>class</span> <span>ZodType<span>&lt;</span>
  Output <span>=</span> <span>any</span><span>,</span>
  Def <span>extends</span> ZodTypeDef <span>=</span> ZodTypeDef<span>,</span>
  Input <span>=</span> Output
<span>&gt;</span></span> <span>{</span> <span>...</span> <span>}</span></code></pre><p>By constraining these in your generic input, you can limit what schemas are allowable as inputs to your function:</p><pre><code><span>function</span> <span><span>makeSchemaOptional</span><span><span>&lt;</span><span>T</span> <span>extends</span> z<span>.</span>ZodType<span>&lt;</span><span>string</span><span>&gt;&gt;</span></span></span><span>(</span>schema<span>:</span> <span>T</span><span>)</span> <span>{</span>
  <span>return</span> schema<span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span>
<span>}</span>

<span>makeSchemaOptional</span><span>(</span>z<span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// works fine</span>

<span>makeSchemaOptional</span><span>(</span>z<span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType&lt;string, ZodTypeDef, string&gt;'</span></code></pre><h3><a href="https://zod.dev/?id=error-handling"><span>Error handling</span></a></h3><p>Zod provides a subclass of Error called <code>ZodError</code>. ZodErrors contain an <code>issues</code> array containing detailed information about the validation problems.</p><pre><code><span>const</span> result <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>safeParse</span><span>(</span><span>{</span> name<span>:</span> <span>12</span> <span>}</span><span>)</span><span>;</span>

<span>if</span> <span>(</span><span>!</span>result<span>.</span>success<span>)</span> <span>{</span>
  result<span>.</span>error<span>.</span>issues<span>;</span>
  <span>/* [
      {
        "code": "invalid_type",
        "expected": "string",
        "received": "number",
        "path": [ "name" ],
        "message": "Expected string, received number"
      }
  ] */</span>
<span>}</span></code></pre><blockquote>
<p>For detailed information about the possible error codes and how to customize error messages, check out the dedicated error handling guide: <a href="https://zod.dev/ERROR_HANDLING">ERROR_HANDLING.md</a></p></blockquote>
<p>Zod's error reporting emphasizes <em>completeness</em> and <em>correctness</em>. 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 <a href="https://github.com/causaly/zod-validation-error"><code>zod-validation-error</code></a></p><h3><a href="https://zod.dev/?id=error-formatting"><span>Error formatting</span></a></h3><p>You can use the <code>.format()</code> method to convert this error into a nested object.</p><pre><code><span>const</span> result <span>=</span> z
  <span>.</span><span>object</span><span>(</span><span>{</span>
    name<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>safeParse</span><span>(</span><span>{</span> name<span>:</span> <span>12</span> <span>}</span><span>)</span><span>;</span>

<span>if</span> <span>(</span><span>!</span>result<span>.</span>success<span>)</span> <span>{</span>
  <span>const</span> formatted <span>=</span> result<span>.</span>error<span>.</span><span>format</span><span>(</span><span>)</span><span>;</span>
  <span>/* {
    name: { _errors: [ 'Expected string, received number' ] }
  } */</span>

  formatted<span>.</span>name<span>?.</span>_errors<span>;</span>
  <span>// =&gt; ["Expected string, received number"]</span>
<span>}</span></code></pre><h2><a href="https://zod.dev/?id=comparison"><span>Comparison</span></a></h2><p>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.</p>





<h3><a href="https://zod.dev/?id=joi"><span>Joi</span></a></h3><p><a href="https://github.com/hapijs/joi">https://github.com/hapijs/joi</a></p><p>Doesn't support static type inference 😕</p><h3><a href="https://zod.dev/?id=yup"><span>Yup</span></a></h3><p><a href="https://github.com/jquense/yup">https://github.com/jquense/yup</a></p><p>Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.</p><ul><li>Supports casting and transforms</li><li>All object fields are optional by default</li><li>Missing promise schemas</li><li>Missing function schemas</li><li>Missing union &amp; intersection schemas</li></ul>

<h3><a href="https://zod.dev/?id=io-ts"><span>io-ts</span></a></h3><p><a href="https://github.com/gcanti/io-ts">https://github.com/gcanti/io-ts</a></p><p>io-ts is an excellent library by gcanti. The API of io-ts heavily inspired the design of Zod.</p><p>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:</p><pre><code><span>import</span> <span>*</span> <span>as</span> t <span>from</span> <span>"io-ts"</span><span>;</span>

<span>const</span> <span>A</span> <span>=</span> t<span>.</span><span>type</span><span>(</span><span>{</span>
  foo<span>:</span> t<span>.</span><span>string</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>B</span> <span>=</span> t<span>.</span><span>partial</span><span>(</span><span>{</span>
  bar<span>:</span> t<span>.</span><span>number</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>C</span> <span>=</span> t<span>.</span><span>intersection</span><span>(</span><span>[</span><span>A</span><span>,</span> <span>B</span><span>]</span><span>)</span><span>;</span>

<span>type</span> <span><span>C</span></span> <span>=</span> t<span>.</span>TypeOf<span>&lt;</span><span>typeof</span> <span>C</span><span>&gt;</span><span>;</span>
<span>// returns { foo: string; bar?: number | undefined }</span></code></pre><p>You must define the required and optional props in separate object validators, pass the optionals through <code>t.partial</code> (which marks all properties as optional), then combine them with <code>t.intersection</code> .</p><p>Consider the equivalent in Zod:</p><pre><code><span>const</span> <span>C</span> <span>=</span> z<span>.</span><span>object</span><span>(</span><span>{</span>
  foo<span>:</span> z<span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  bar<span>:</span> z<span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span><span>C</span></span> <span>=</span> z<span>.</span>infer<span>&lt;</span><span>typeof</span> <span>C</span><span>&gt;</span><span>;</span>
<span>// returns { foo: string; bar?: number | undefined }</span></code></pre><p>This more declarative API makes schema definitions vastly more concise.</p><p><code>io-ts</code> also requires the use of gcanti's functional programming library <code>fp-ts</code> to parse results and handle errors. This is another fantastic resource for developers looking to keep their codebase strictly functional. But depending on <code>fp-ts</code> necessarily comes with a lot of intellectual overhead; a developer has to be familiar with functional programming concepts and the <code>fp-ts</code> nomenclature to use the library.</p><ul><li>Supports codecs with serialization &amp; deserialization transforms</li><li>Supports branded types</li><li>Supports advanced functional programming, higher-kinded types, <code>fp-ts</code> compatibility</li><li>Missing object methods: (pick, omit, partial, deepPartial, merge, extend)</li><li>Missing nonempty arrays with proper typing (<code>[T, ...T[]]</code>)</li><li>Missing promise schemas</li><li>Missing function schemas</li></ul><h3><a href="https://zod.dev/?id=runtypes"><span>Runtypes</span></a></h3><p><a href="https://github.com/pelotom/runtypes">https://github.com/pelotom/runtypes</a></p><p>Good type inference support.</p><ul><li>Supports "pattern matching": computed properties that distribute over unions</li><li>Missing object methods: (deepPartial, merge)</li><li>Missing nonempty arrays with proper typing (<code>[T, ...T[]]</code>)</li><li>Missing promise schemas</li><li>Missing error customization</li></ul><h3><a href="https://zod.dev/?id=ow"><span>Ow</span></a></h3><p><a href="https://github.com/sindresorhus/ow">https://github.com/sindresorhus/ow</a></p><p>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 (e.g. <code>int32Array</code> , see full list in their README).</p><p>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.</p><h2><a href="https://zod.dev/?id=changelog"><span>Changelog</span></a></h2><p>View the changelog at <a href="https://zod.dev/CHANGELOG">CHANGELOG.md</a></p></article></section></div>||||I||||    * Table of contents
    * Introduction
    * Sponsors
        + Ecosystem
    * Installation
        + Requirements
        + From npm (Node/Bun)
        + From deno.land/x (Deno)
    * Basic usage
    * Primitives
    * Coercion for primitives
    * Literals
    * Strings
        + Datetimes
        + Dates
        + Times
        + IP addresses
    * Numbers
    * BigInts
    * NaNs
    * Booleans
    * Dates
    * Zod enums
    * Native enums
    * Optionals
    * Nullables
    * Objects
        + .shape
        + .keyof
        + .extend
        + .merge
        + .pick/.omit
        + .partial
        + .deepPartial
        + .required
        + .passthrough
        + .strict
        + .strip
        + .catchall
    * Arrays
        + .element
        + .nonempty
        + .min/.max/.length
    * Tuples
    * Unions
    * Discriminated unions
    * Records
    * Maps
    * Sets
    * Intersections
    * Recursive types
        + ZodType with ZodEffects
        + JSON type
        + Cyclical objects
    * Promises
    * Instanceof
    * Functions
    * Preprocess
    * Custom schemas
    * Schema methods
        + .parse
        + .parseAsync
        + .safeParse
        + .safeParseAsync
        + .refine
        + .superRefine
        + .transform
        + .default
        + .describe
        + .catch
        + .optional
        + .nullable
        + .nullish
        + .array
        + .promise
        + .or
        + .and
        + .brand
        + .readonly
        + .pipe
    * Guides and concepts
        + Type inference
        + Writing generic functions
        + Error handling
        + Error formatting
    * Comparison
        + Joi
        + Yup
        + io-ts
        + Runtypes
        + Ow
    * Changelog

Zod

✨ https://zod.dev ✨
TypeScript-first schema validation with static type inference


  Documentation • Discord • npm • deno • Issues • @colinhacks • tRPC




Table of contents

These docs have been translated into Chinese.

  * Table of contents
  * Introduction
      + Sponsors
          o Platinum
          o Gold
          o Silver
          o Bronze
          o Copper
      + Ecosystem
          o Resources
          o API libraries
          o Form integrations
          o Zod to X
          o X to Zod
          o Mocking
          o Powered by Zod
          o Utilities for Zod
  * Installation
      + Requirements
      + From npm (Node/Bun)
      + From deno.land/x (Deno)
  * Basic usage
  * Primitives
  * Coercion for primitives
  * Literals
  * Strings
      + Datetimes
      + Dates
      + Times
      + IP addresses
  * Numbers
  * BigInts
  * NaNs
  * Booleans
  * Dates
  * Zod enums
  * Native enums
  * Optionals
  * Nullables
  * Objects
      + .shape
      + .keyof
      + .extend
      + .merge
      + .pick/.omit
      + .partial
      + .deepPartial
      + .required
      + .passthrough
      + .strict
      + .strip
      + .catchall
  * Arrays
      + .element
      + .nonempty
      + .min/.max/.length
  * Tuples
  * Unions
  * Discriminated unions
  * Records
      + Record key type
  * Maps
  * Sets
  * Intersections
  * Recursive types
      + ZodType with ZodEffects
      + JSON type
      + Cyclical objects
  * Promises
  * Instanceof
  * Functions
  * Preprocess
  * Custom schemas
  * Schema methods
      + .parse
      + .parseAsync
      + .safeParse
      + .safeParseAsync
      + .refine
          o Arguments
          o Customize error path
          o Asynchronous refinements
          o Relationship to transforms
      + .superRefine
          o Abort early
          o Type refinements
      + .transform
          o Chaining order
          o Validating during transform
          o Relationship to refinements
          o Async transforms
      + .default
      + .describe
      + .catch
      + .optional
      + .nullable
      + .nullish
      + .array
      + .promise
      + .or
      + .and
      + .brand
      + .readonly
      + .pipe
          o You can use .pipe() to fix common issues with z.coerce.
  * Guides and concepts
      + Type inference
      + Writing generic functions
          o Constraining allowable inputs
      + Error handling
      + Error formatting
  * Comparison
      + Joi
      + Yup
      + io-ts
      + Runtypes
      + Ow
  * Changelog

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
  * Works with plain JavaScript too! You don't need to use TypeScript.

Sponsors

Sponsorship at any level is appreciated and encouraged. If you built a paid product using Zod, consider one of the corporate tiers.


Diamond




  The most comprehensive User Management Platform
  clerk.com



Platinum

                                          
    Serverless Postgres — Ship faster     
                neon.tech                 
                                          
                                          
Build AI apps and workflows with Retool AI
                retool.com                
                                          
                                          
       Generate best-in-class SDKs        
             stainlessapi.com             
                                          
                                          
 SDKs & Terraform providers for your API  
              speakeasy.com               
                                          



Gold

                                                 
PropelAuth    Cerbos     Scalar     Trigger.dev  
                                                 
Transloadit  Infisical    Whop     CryptoJobsList
                                                 
  Plain.      Inngest   Storyblok       Mux      



Silver

      
      



Bronze

Brandon Bayer  Jiří Brabec     Alex Johansson       Fungible Systems         
Adaptable      Avana Wallet    Jason Lengstorf      Global Illumination, Inc.
MasterBorn     Ryan Palmer     Michael Sweeney      Nextbase                 
Remotion       Connor Sinnott  Mohammad-Ali A'râbi  Supatool                 


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 or start a Discussion. I'll add it below and tweet it out.

Resources

  * Total TypeScript Zod Tutorial by @mattpocockuk
  * Fixing TypeScript's Blindspot: Runtime Typechecking by @jherr

API libraries

  * tRPC: Build end-to-end typesafe APIs without GraphQL.
  * @anatine/zod-nestjs: Helper methods for using Zod in a NestJS project.
  * zod-endpoints: Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
  * zhttp: An OpenAPI compatible, strictly typed http library with Zod input and response validation.
  * 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: A typescript API client with runtime and compile time validation backed by axios and zod.
  * express-zod-api: Build Express-based APIs with I/O schema validation and custom middlewares.
  * tapiduck: End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler.
  * koa-zod-router: Create typesafe routes in Koa with I/O validation using Zod.
  * zod-sockets: Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs

Form integrations

  * react-hook-form: A first-party Zod resolver for React Hook Form.
  * zod-validation-error: Generate user-friendly error messages from ZodErrors.
  * zod-formik-adapter: A community-maintained Formik adapter for Zod.
  * react-zorm: Standalone <form> generation and validation for React using Zod.
  * zodix: Zod utilities for FormData and URLSearchParams in Remix loaders and actions.
  * conform: A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js.
  * remix-params-helper: Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.
  * formik-validator-zod: Formik-compliant validator library that simplifies using Zod with Formik.
  * zod-i18n-map: Useful for translating Zod error messages.
  * @modular-forms/solid: Modular form library for SolidJS that supports Zod for validation.
  * houseform: A React form library that uses Zod for validation.
  * sveltekit-superforms: Supercharged form library for SvelteKit with Zod validation.
  * mobx-zod-form: Data-first form builder based on MobX & Zod.
  * @vee-validate/zod: Form library for Vue.js with Zod schema validation.

Zod to X

  * zod-to-ts: Generate TypeScript definitions from Zod schemas.
  * zod-to-json-schema: Convert your Zod schemas into JSON Schemas.
  * @anatine/zod-openapi: Converts a Zod schema to an OpenAPI v3.x SchemaObject.
  * zod-fast-check: Generate fast-check arbitraries from Zod schemas.
  * zod-dto: Generate Nest.js DTOs from a Zod schema.
  * fastify-type-provider-zod: Create Fastify type providers from Zod schemas.
  * zod-to-openapi: Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters.
  * nestjs-graphql-zod: Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.
  * zod-openapi: Create full OpenAPI v3.x documentation from Zod schemas.
  * fastify-zod-openapi: Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas.
  * typeschema: Universal adapter for schema validation.

X to Zod

  * ts-to-zod: Convert TypeScript definitions into Zod schemas.
  * @runtyping/zod: Generate Zod from static types & JSON schema.
  * json-schema-to-zod: Convert your JSON Schemas into Zod schemas. Live demo.
  * json-to-zod: Convert JSON objects into Zod schemas. Live demo.
  * graphql-codegen-typescript-validation-schema: GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.
  * zod-prisma: Generate Zod schemas from your Prisma schema.
  * Supervillain: Generate Zod schemas from your Go structs.
  * prisma-zod-generator: Emit Zod schemas from your Prisma schema.
  * drizzle-zod: Emit Zod schemas from your Drizzle schema.
  * prisma-trpc-generator: Emit fully implemented tRPC routers and their validation schemas using Zod.
  * zod-prisma-types Create Zod types from your Prisma models.
  * quicktype: Convert JSON objects and JSON schemas into Zod schemas.
  * @sanity-typed/zod: Generate Zod Schemas from Sanity Schemas.
  * java-to-zod: Convert POJOs to Zod schemas
  * Orval: Generate Zod schemas from OpenAPI schemas
  * Kubb: Generate SDKs and Zod schemas from your OpenAPI schemas

Mocking

  * @anatine/zod-mock: Generate mock data from a Zod schema. Powered by faker.js.
  * zod-mocking: Generate mock data from your Zod schemas.
  * zod-fixture: Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.
  * zocker: Generate plausible mock-data from your schemas.
  * zodock Generate mock data based on Zod schemas.
  * zod-schema-faker Generates mock data from Zod schemas. Powered by @faker-js/faker and randexp.js

Powered by Zod

  * freerstore: Firestore cost optimizer.
  * slonik: Node.js Postgres client with strong Zod integration.
  * soly: Create CLI applications with zod.
  * pastel: Create CLI applications with react, zod, and ink.
  * zod-xlsx: A xlsx based resource validator using Zod schemas.
  * znv: Type-safe environment parsing and validation for Node.js with Zod schemas.
  * zod-config: Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.

Utilities for Zod

  * zod_utilz: Framework agnostic utilities for Zod.
  * zod-playground: A tool for learning and testing Zod schema validation functionalities. Link.
  * zod-sandbox: Controlled environment for testing zod schemas. Live demo.
  * zod-dev: Conditionally disables Zod runtime parsing in production.
  * zod-accelerator: Accelerates Zod's throughput up to ~100x.

Installation

Requirements

  * TypeScript 4.5+!

  * You must enable strict mode in your tsconfig.json. This is a best practice for all TypeScript projects.

    // tsconfig.json
    {
      // ...
      "compilerOptions": {
        // ...
        "strict": true
      }
    }

From npm (Node/Bun)

npm install zod       # npm
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:

npm install zod@canary       # npm
yarn add zod@canary          # yarn
bun add zod@canary           # bun
pnpm add zod@canary          # pnpm

From deno.land/x (Deno)

Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on deno.land/x. The latest version can be imported like so:

import { z } from "https://deno.land/x/zod/mod.ts";

You can also specify a particular version:

import { z } from "https://deno.land/x/zod@v3.16.1/mod.ts";

The rest of this README assumes you are using npm and importing directly from the "zod" package.

Basic usage

Creating a simple string schema

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

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 }

Primitives

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();

Coercion for primitives

Zod now provides a more convenient way to coerce primitive values.

const schema = z.coerce.string();
schema.parse("tuna"); // => "tuna"
schema.parse(12); // => "12"

During the parsing step, the input is passed through the String() function, which is a JavaScript built-in for coercing data into strings.

schema.parse(12); // => "12"
schema.parse(true); // => "true"
schema.parse(undefined); // => "undefined"
schema.parse(null); // => "null"

The returned schema is a normal ZodString instance so you can use all string methods.

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.

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 value is coerced to true, and any falsy value is coerced to 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

For more control over coercion logic, consider using z.preprocess or z.pipe().

Literals

Literal schemas represent a literal type, like "hello world" or 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"

Currently there is no support for Date literals in Zod. If you have a use case for this feature, please file an issue.

Strings

Zod includes a handful of string-specific validations.

// 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();

Check out validator.js for a bunch of other useful string validation functions that can be used in conjunction with Refinements.

You can customize some common error messages when creating a string schema.

const name = z.string({
  required_error: "Name is required",
  invalid_type_error: "Name must be a string",
});

When using validation methods, you can pass in an additional argument to provide a custom error message.

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" });

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.

const datetime = z.string().datetime();

datetime.parse("2020-01-01T00:00:00Z"); // pass
datetime.parse("2020-01-01T00:00:00.123Z"); // pass
datetime.parse("2020-01-01T00:00:00.123456Z"); // pass (arbitrary precision)
datetime.parse("2020-01-01T00:00:00+02:00"); // fail (no offsets allowed)

Timezone offsets can be allowed by setting the offset option to true.

const datetime = z.string().datetime({ offset: true });

datetime.parse("2020-01-01T00:00:00+02:00"); // pass
datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional)
datetime.parse("2020-01-01T00:00:00.123+0200"); // pass (millis optional)
datetime.parse("2020-01-01T00:00:00.123+02"); // pass (only offset hours)
datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported)

You can additionally constrain the allowable precision. By default, arbitrary sub-second precision is supported (but optional).

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

Dates

Added in Zod 3.23

The z.string().date() method validates strings in the format 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

Times

Added in Zod 3.23

The z.string().time() method validates strings in the format HH:MM:SS[.s+]. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind.

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)

You can set the precision option to constrain the allowable decimal 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

IP addresses

The z.string().ip() method by default validate IPv4 and 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

You can additionally set the 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

Numbers

You can customize certain error messages when creating a number schema.

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.

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.

z.number().lte(5, { message: "this👏is👏too👏big" });

BigInts

Zod includes a handful of bigint-specific validations.

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.

NaNs

You can customize certain error messages when creating a nan schema.

const isNaN = z.nan({
  required_error: "isNaN is required",
  invalid_type_error: "isNaN must be 'not a number'",
});

Booleans

You can customize certain error messages when creating a boolean schema.

const isActive = z.boolean({
  required_error: "isActive is required",
  invalid_type_error: "isActive must be a boolean",
});

Dates

Use z.date() to validate Date instances.

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.

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.

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, use z.coerce.date() to pass the input through 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

For older zod versions, use z.preprocess like described in this thread.

Zod enums

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 for details.

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.

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:

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:

FishEnum.options; // ["Salmon", "Tuna", "Trout"];

.exclude/.extract()

You can create subsets of a Zod enum with the .exclude and .extract methods.

const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]);
const SalmonAndTrout = FishEnum.extract(["Salmon", "Trout"]);
const TunaOnly = FishEnum.exclude(["Salmon", "Trout"]);

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

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

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+!

const Fruits = {
  Apple: "apple",
  Banana: "banana",
  Cantaloupe: 3,
} as const;

const FruitEnum = z.nativeEnum(Fruits);
type FruitEnum = z.infer<typeof FruitEnum>; // "apple" | "banana" | 3

FruitEnum.parse("apple"); // passes
FruitEnum.parse("banana"); // passes
FruitEnum.parse(3); // passes
FruitEnum.parse("Cantaloupe"); // fails

You can access the underlying object with the .enum property:

FruitEnum.enum.Apple; // "apple"

Optionals

You can make any schema optional with z.optional(). This wraps the schema in a ZodOptional instance and returns the result.

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.

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().

const stringSchema = z.string();
const optionalString = stringSchema.optional();
optionalString.unwrap() === stringSchema; // true

Nullables

Similarly, you can create nullable types with z.nullable().

const nullableString = z.nullable(z.string());
nullableString.parse("asdf"); // => "asdf"
nullableString.parse(null); // => null

Or use the .nullable() method.

const E = z.string().nullable(); // equivalent to nullableString
type E = z.infer<typeof E>; // string | null

Extract the inner schema with .unwrap().

const stringSchema = z.string();
const nullableString = stringSchema.nullable();
nullableString.unwrap() === stringSchema; // true

Objects

// 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

Use .shape to access the schemas for a particular key.

Dog.shape.name; // => string schema
Dog.shape.age; // => number schema

.keyof

Use .keyof to create a ZodEnum schema from the keys of an object schema.

const keySchema = Dog.keyof();
keySchema; // ZodEnum<["name", "age"]>

.extend

You can add additional fields to an object schema with the .extend method.

const DogWithBreed = Dog.extend({
  breed: z.string(),
});

You can use .extend to overwrite fields! Be careful with this power!

.merge

Equivalent to 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 }

If the two schemas share keys, the properties of B overrides the property of A. The returned schema also inherits the "unknownKeys" policy (strip/strict/passthrough) and the catchall schema of B.

.pick/.omit

Inspired by TypeScript's built-in Pick and Omit utility types, all Zod object schemas have .pick and .omit methods that return a modified version. Consider this Recipe schema:

const Recipe = z.object({
  id: z.string(),
  name: z.string(),
  ingredients: z.array(z.string()),
});

To only keep certain keys, use .pick .

const JustTheName = Recipe.pick({ name: true });
type JustTheName = z.infer<typeof JustTheName>;
// => { name: string }

To remove certain keys, use .omit .

const NoIDRecipe = Recipe.omit({ id: true });

type NoIDRecipe = z.infer<typeof NoIDRecipe>;
// => { name: string, ingredients: string[] }

.partial

Inspired by the built-in TypeScript utility type Partial, the .partial method makes all properties optional.

Starting from this object:

const user = z.object({
  email: z.string(),
  username: z.string(),
});
// { email: string; username: string }

We can create a partial version:

const partialUser = user.partial();
// { email?: string | undefined; username?: string | undefined }

You can also specify which properties to make optional:

const optionalEmail = user.partial({
  email: true,
});
/*
{
  email?: string | undefined;
  username: string
}
*/

.deepPartial

The .partial method is shallow — it only applies one level deep. There is also a "deep" version:

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}[]
}
*/

Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.

.required

Contrary to the .partial method, the .required method makes all properties required.

Starting from this object:

const user = z
  .object({
    email: z.string(),
    username: z.string(),
  })
  .partial();
// { email?: string | undefined; username?: string | undefined }

We can create a required version:

const requiredUser = user.required();
// { email: string; username: string }

You can also specify which properties to make required:

const requiredEmail = user.required({
  email: true,
});
/*
{
  email: string;
  username?: string | undefined;
}
*/

.passthrough

By default Zod object schemas strip out unrecognized keys during parsing.

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

person.parse({
  name: "bob dylan",
  extraKey: 61,
});
// => { name: "bob dylan" }
// extraKey has been stripped

Instead, if you want to pass through unknown keys, use .passthrough() .

person.passthrough().parse({
  name: "bob dylan",
  extraKey: 61,
});
// => { name: "bob dylan", extraKey: 61 }

.strict

By default Zod object schemas strip out unrecognized keys during parsing. You can disallow unknown keys with .strict() . If there are any unknown keys in the input, Zod will throw an error.

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

person.parse({
  name: "bob dylan",
  extraKey: 61,
});
// => throws ZodError

.strip

You can use the .strip method to reset an object schema to the default behavior (stripping unrecognized keys).

.catchall

You can pass a "catchall" schema into an object schema. All unknown keys will be validated against it.

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

Using .catchall() obviates .passthrough() , .strip() , or .strict(). All keys are now considered "known".

Arrays

const stringArray = z.array(z.string());

// equivalent
const stringArray = z.string().array();

Be careful with the .array() method. It returns a new ZodArray instance. This means the order in which you call methods matters. For instance:

z.string().optional().array(); // (string | undefined)[]
z.string().array().optional(); // string[] | undefined

.element

Use .element to access the schema for an element of the array.

stringArray.element; // => string schema

.nonempty

If you want to ensure that an array contains at least one element, use .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

You can optionally specify a custom error message:

// 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

Unlike .nonempty() these methods do not change the inferred type.

Tuples

Unlike arrays, tuples have a fixed number of elements and each element can have a different type.

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 }]

A variadic ("rest") argument can be added with the .rest method.

const variadicTuple = z.tuple([z.string()]).rest(z.number());
const result = variadicTuple.parse(["hello", 1, 2, 3]);
// => [string, ...number[]];

Unions

Zod includes a built-in z.union method for composing "OR" types.

const stringOrNumber = z.union([z.string(), z.number()]);

stringOrNumber.parse("foo"); // passes
stringOrNumber.parse(14); // passes

Zod will test the input against each of the "options" in order and return the first value that validates successfully.

For convenience, you can also use the .or method:

const stringOrNumber = z.string().or(z.number());

Optional string validation:

To validate an optional form input, you can union the desired string validation with an empty string literal.

This example validates an input that is optional but needs to contain a valid 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

Discriminated unions

A discriminated union is a union of object schemas that all share a particular key.

type MyUnion =
  | { status: "success"; data: string }
  | { status: "failed"; error: Error };

Such unions can be represented with the z.discriminatedUnion method. This enables faster evaluation, because Zod can check the discriminator key (status in the example above) to determine which schema should be used to parse the input. This makes parsing more efficient and lets Zod report friendlier errors.

With the basic union method, the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".

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" });

You can extract a reference to the array of schemas with the .options property.

myUnion.options; // [ZodObject<...>, ZodObject<...>]

To merge two or more discriminated unions, use .options with destructuring.

const A = z.discriminatedUnion("status", [
  /* options */
]);
const B = z.discriminatedUnion("status", [
  /* options */
]);

const AB = z.discriminatedUnion("status", [...A.options, ...B.options]);

Records

Record schemas are used to validate types such as Record<string, number>. This is particularly useful for storing or caching items by 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 }>

The schema and inferred type can be used like so:

const userStore: UserStore = {};

userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
  name: "Carlotta",
}; // passes

userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
  whatever: "Ice cream sundae",
}; // TypeError

A note on numerical keys

While z.record(keyType, valueType) is able to accept numerical key types and TypeScript's built-in Record type is Record<KeyType, ValueType>, it's hard to represent the TypeScript type Record<number, any> in Zod.

As it turns out, TypeScript's behavior surrounding [k: number] is a little unintuitive:

const testMap: { [k: number]: string } = {
  1: "one",
};

for (const key in testMap) {
  console.log(`${key}: ${typeof key}`);
}
// prints: `1: string`

As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.

Maps

const stringNumberMap = z.map(z.string(), z.number());

type StringNumberMap = z.infer<typeof stringNumberMap>;
// type StringNumberMap = Map<string, number>

Sets

const numberSet = z.set(z.number());
type NumberSet = z.infer<typeof numberSet>;
// type NumberSet = Set<number>

Set schemas can be further constrained with the following utility methods.

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

Intersections

Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.

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);

Though in many cases, it is recommended to use A.merge(B) to merge two objects. The .merge method returns a new ZodObject instance, whereas A.and(B) returns a less useful ZodIntersection instance that lacks common object methods like pick and omit.

const a = z.union([z.number(), z.string()]);
const b = z.union([z.number(), z.boolean()]);
const c = z.intersection(a, b);

type c = z.infer<typeof c>; // => number

Recursive types

You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".

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

type Category = z.infer<typeof baseCategorySchema> & {
  subcategories: Category[];
};

const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
  subcategories: z.lazy(() => categorySchema.array()),
});

categorySchema.parse({
  name: "People",
  subcategories: [
    {
      name: "Politicians",
      subcategories: [
        {
          name: "Presidents",
          subcategories: [],
        },
      ],
    },
  ],
}); // passes

Thanks to crasite for this example.

ZodType with ZodEffects

When using z.ZodType with z.ZodEffects ( .refine, .transform, preprocess, etc... ), you will need to define the input and output types of the schema. 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()),
});

Thanks to marcus13371337 and JoelBeeldi for this example.

JSON type

If you want to validate any JSON value, you can use the snippet below.

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);

Thanks to ggoodman for suggesting this.

Cyclical objects

Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop in some cases.

To detect cyclical objects before they cause problems, consider this approach.

Promises

const numberPromise = z.promise(z.number());

"Parsing" works a little differently with promise schemas. Validation happens in two parts:

 1. Zod synchronously checks that the input is an instance of Promise (i.e. an object with .then and .catch methods.).
 2. Zod uses .then to attach an additional validation step onto the existing Promise. You'll have to use .catch on the returned Promise to handle validation failures.
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
};

Instanceof

You can use z.instanceof to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.

class Test {
  name: string;
}

const TestSchema = z.instanceof(Test);

const blob: any = "whatever";
TestSchema.parse(new Test()); // passes
TestSchema.parse(blob); // throws

Functions

Zod also lets you define "function schemas". This makes it easy to validate the inputs and outputs of a function without intermixing your validation code and "business logic".

You can create a function schema with z.function(args, returnType) .

const myFunction = z.function();

type myFunction = z.infer<typeof myFunction>;
// => ()=>unknown

Define inputs and outputs.

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

Function schemas have an .implement() method which accepts a function and returns a new function that automatically validates its inputs and outputs.

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

If you only care about validating inputs, just don't call the .returns() method. The output type will be inferred from the implementation.

You can use the special z.void() option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)

const myFunction = z
  .function()
  .args(z.string())
  .implement((arg) => {
    return [arg.length];
  });

myFunction; // (arg: string)=>number[]

Extract the input and output schemas from a function schema.

myFunction.parameters();
// => ZodTuple<[ZodString, ZodNumber]>

myFunction.returnType();
// => ZodBoolean

Preprocess

Zod now supports primitive coercion without the need for .preprocess(). See the coercion docs for more information.

Typically Zod operates under a "parse then transform" paradigm. Zod validates the input first, then passes it through a chain of transformation functions. (For more information about transforms, read the .transform docs.)

But sometimes you want to apply some transform to the input before parsing happens. A common use case: type coercion. Zod enables this with the z.preprocess().

const castToString = z.preprocess((val) => String(val), z.string());

This returns a ZodEffects instance. ZodEffects is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.

Custom schemas

You can create a Zod schema for any TypeScript type by using z.custom(). This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.

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;

If you don't provide a validation function, Zod will allow any value. This can be dangerous!

z.custom<{ arg: string }>(); // performs no validation

You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of .refine.

z.custom<...>((val) => ..., "custom error message");

Schema methods

All Zod schemas contain certain methods.

.parse

.parse(data: unknown): T

Given any Zod schema, you can call its .parse method to check data is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.

IMPORTANT: The value returned by .parse is a deep clone of the variable you passed in.

const stringSchema = z.string();

stringSchema.parse("fish"); // => returns "fish"
stringSchema.parse(12); // throws error

.parseAsync

.parseAsync(data:unknown): Promise<T>

If you use asynchronous refinements or transforms (more on those later), you'll need to use .parseAsync.

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

await stringSchema.parseAsync("hello"); // => returns "hello"
await stringSchema.parseAsync("hello world"); // => throws error

.safeParse

.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }

If you don't want Zod to throw errors when validation fails, use .safeParse. This method returns an object containing either the successfully parsed data or a ZodError instance containing detailed information about the validation problems.

stringSchema.safeParse(12);
// => { success: false; error: ZodError }

stringSchema.safeParse("billie");
// => { success: true; data: 'billie' }

The result is a discriminated union, so you can handle errors very conveniently:

const result = stringSchema.safeParse("billie");
if (!result.success) {
  // handle error then return
  result.error;
} else {
  // do something
  result.data;
}

.safeParseAsync

Alias: .spa

An asynchronous version of safeParse.

await stringSchema.safeParseAsync("billie");

For convenience, this has been aliased to .spa:

await stringSchema.spa("billie");

.refine

.refine(validator: (data:T)=>any, params?: RefineParams)

Zod lets you provide custom validation logic via refinements. (For advanced features like creating multiple issues and customizing error codes, see .superRefine.)

Zod was designed to mirror TypeScript as closely as possible. But there are many so-called "refinement types" you may wish to check for that can't be represented in TypeScript's type system. For instance: checking that a number is an integer or that a string is a valid email address.

For example, you can define a custom validation check on any Zod schema with .refine :

const myString = z.string().refine((val) => val.length <= 255, {
  message: "String can't be more than 255 characters",
});

⚠️ Refinement functions should not throw. Instead they should return a falsy value to signal failure.

Arguments

As you can see, .refine takes two arguments.

 1. The first is the validation function. This function takes one input (of type T — the inferred type of the schema) and returns any. Any truthy value will pass validation. (Prior to zod@1.6.2 the validation function had to return a boolean.)
 2. The second argument accepts some options. You can use this to customize certain error-handling behavior:
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;
};

For advanced cases, the second argument can also be a function that returns RefineParams.

const longString = z.string().refine(
  (val) => val.length > 10,
  (val) => ({ message: `${val} is not more than 10 characters` })
);

Customize error path

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" });

Because you provided a path parameter, the resulting error will be:

ZodError {
  issues: [{
    "code": "custom",
    "path": [ "confirm" ],
    "message": "Passwords don't match"
  }]
}

Asynchronous refinements

Refinements can also be async:

const userId = z.string().refine(async (id) => {
  // verify that ID exists in database
  return true;
});

⚠️ If you use async refinements, you must use the .parseAsync method to parse data! Otherwise Zod will throw an error.

Relationship to transforms

Transforms and refinements can be interleaved:

z.string()
  .transform((val) => val.length)
  .refine((val) => val > 25);

.superRefine

The .refine method is actually syntactic sugar atop a more versatile (and verbose) method called superRefine. Here's an example:

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.`,
    });
  }
});

You can add as many issues as you like. If ctx.addIssue is not called during the execution of the function, validation passes.

Normally refinements always create issues with a ZodIssueCode.custom error code, but with superRefine it's possible to throw issues of any ZodIssueCode. Each issue code is described in detail in the Error Handling guide: ERROR_HANDLING.md.

Abort early

By default, parsing will continue even after a refinement check fails. For instance, if you chain together multiple refinements, they will all be executed. However, it may be desirable to abort early to prevent later refinements from being executed. To achieve this, pass the fatal flag to ctx.addIssue and return 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",
    });
  }
});

Type refinements

If you provide a type predicate to .refine() or .superRefine(), the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:

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`!");

⚠️ You must use ctx.addIssue() instead of returning a boolean value to indicate whether the validation passes. If ctx.addIssue is not called during the execution of the function, validation passes.

.transform

To transform data after parsing, use the transform method.

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

stringToNumber.parse("string"); // => 6

Chaining order

Note that stringToNumber above is an instance of the ZodEffects subclass. It is NOT an instance of ZodString. If you want to use the built-in methods of ZodString (e.g. .email()) you must apply those methods before any transforms.

const emailToDomain = z
  .string()
  .email()
  .transform((val) => val.split("@")[1]);

emailToDomain.parse("colinhacks@example.com"); // => example.com

Validating during transform

The .transform method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining transform and refine.

As with .superRefine, the transform function receives a ctx object with an addIssue method that can be used to register validation issues.

const numberInString = z.string().transform((val, ctx) => {
  const parsed = parseInt(val);
  if (isNaN(parsed)) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "Not a number",
    });

    // This is a special symbol you can use to
    // return early from the transform function.
    // It has type `never` so it does not affect the
    // inferred return type.
    return z.NEVER;
  }
  return parsed;
});

Relationship to refinements

Transforms and refinements can be interleaved. These will be executed in the order they are declared.

const nameToGreeting = z
  .string()
  .transform((val) => val.toUpperCase())
  .refine((val) => val.length > 15)
  .transform((val) => `Hello ${val}`)
  .refine((val) => val.indexOf("!") === -1);

Async transforms

Transforms can also be async.

const IdToUser = z
  .string()
  .uuid()
  .transform(async (id) => {
    return await getUserById(id);
  });

⚠️ If your schema contains asynchronous transforms, you must use .parseAsync() or .safeParseAsync() to parse data. Otherwise Zod will throw an error.

.default

You can use transforms to implement the concept of "default values" in Zod.

const stringWithDefault = z.string().default("tuna");

stringWithDefault.parse(undefined); // => "tuna"

Optionally, you can pass a function into .default that will be re-executed whenever a default value needs to be generated:

const numberWithRandomDefault = z.number().default(Math.random);

numberWithRandomDefault.parse(undefined); // => 0.4413456736055323
numberWithRandomDefault.parse(undefined); // => 0.1871840107401901
numberWithRandomDefault.parse(undefined); // => 0.7223408162401552

Conceptually, this is how Zod processes default values:

 1. If the input is undefined, the default value is returned
 2. Otherwise, the data is parsed using the base schema

.describe

Use .describe() to add a description property to the resulting schema.

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…

This can be useful for documenting a field, for example in a JSON Schema using a library like zod-to-json-schema).

.catch

Use .catch() to provide a "catch value" to be returned in the event of a parsing error.

const numberWithCatch = z.number().catch(42);

numberWithCatch.parse(5); // => 5
numberWithCatch.parse("tuna"); // => 42

Optionally, you can pass a function into .catch that will be re-executed whenever a default value needs to be generated. A ctx object containing the caught error will be passed into this function.

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

Conceptually, this is how Zod processes "catch values":

 1. The data is parsed using the base schema
 2. If the parsing fails, the "catch value" is returned

.optional

A convenience method that returns an optional version of a schema.

const optionalString = z.string().optional(); // string | undefined

// equivalent to
z.optional(z.string());

.nullable

A convenience method that returns a nullable version of a schema.

const nullableString = z.string().nullable(); // string | null

// equivalent to
z.nullable(z.string());

.nullish

A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both undefined and null. Read more about the concept of "nullish" in the TypeScript 3.7 release notes.

const nullishString = z.string().nullish(); // string | null | undefined

// equivalent to
z.string().nullable().optional();

.array

A convenience method that returns an array schema for the given type:

const stringArray = z.string().array(); // string[]

// equivalent to
z.array(z.string());

.promise

A convenience method for promise types:

const stringPromise = z.string().promise(); // Promise<string>

// equivalent to
z.promise(z.string());

.or

A convenience method for union types.

const stringOrNumber = z.string().or(z.number()); // string | number

// equivalent to
z.union([z.string(), z.number()]);

.and

A convenience method for creating intersection types.

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's type system is structural, which means that any two types that are structurally equivalent are considered the same.

type Cat = { name: string };
type Dog = { name: string };

const petCat = (cat: Cat) => {};
const fido: Dog = { name: "fido" };
petCat(fido); // works fine

In some cases, its can be desirable to simulate nominal typing inside TypeScript. For instance, you may wish to write a function that only accepts an input that has been validated by Zod. This can be achieved with branded types (AKA opaque types).

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" });

Under the hood, this works by attaching a "brand" to the inferred type using an intersection type. This way, plain/unbranded data structures are no longer assignable to the inferred type of the schema.

const Cat = z.object({ name: z.string() }).brand<"Cat">();
type Cat = z.infer<typeof Cat>;
// {name: string} & {[symbol]: "Cat"}

Note that branded types do not affect the runtime result of .parse. It is a static-only construct.

.readonly

.readonly() => ZodReadonly<this>

This method returns a ZodReadonly schema instance that parses the input using the base schema, then calls Object.freeze() on the result. The inferred type is also marked as 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

The inferred type uses TypeScript's built-in readonly types when relevant.

z.array(z.string()).readonly();
// readonly string[]

z.tuple([z.string(), z.number()]).readonly();
// readonly [string, number]

z.map(z.string(), z.date()).readonly();
// ReadonlyMap<string, Date>

z.set(z.string()).readonly();
// ReadonlySet<string>

.pipe

Schemas can be chained into validation "pipelines". It's useful for easily validating the result after a .transform():

z.string()
  .transform((val) => val.length)
  .pipe(z.number().min(5));

The .pipe() method returns a ZodPipeline instance.

You can use .pipe() to fix common issues with z.coerce .

You can constrain the input to types that work well with your chosen coercion. Then use .pipe() to apply the coercion.

without constrained input:

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

with constrained input:

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

You can also use this technique to avoid coercions that throw uncaught errors.

without constrained input:

const toBigInt = z.coerce.bigint();

// works intuitively
console.log(toBigInt.safeParse("42")); // true

// probably not what you want
console.log(toBigInt.safeParse(null)); // throws uncaught error

with constrained input:

const toNumber = z.number().or(z.string()).pipe(z.coerce.number());
const toBigInt = z.bigint().or(toNumber).pipe(z.coerce.bigint());

// still works intuitively
console.log(toBigInt.safeParse("42").success); // true

// error handled by zod, more likely what you want
console.log(toBigInt.safeParse(null).success); // false

Guides and concepts

Type inference

You can extract the TypeScript type of any schema with z.infer<typeof mySchema> .

const A = z.string();
type A = z.infer<typeof A>; // string

const u: A = 12; // TypeError
const u: A = "asdf"; // compiles

What about transforms?

In reality each Zod schema internally tracks two types: an input and an output. For most schemas (e.g. z.string()) these two are the same. But once you add transforms into the mix, these two values can diverge. For instance z.string().transform(val => val.length) has an input of string and an output of number.

You can separately extract the input and output types like 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

Writing generic functions

With TypeScript generics, you can write reusable functions that accept Zod schemas as parameters. This enables you to create custom validation logic, schema transformations, and more, while maintaining type safety and inference.

When attempting to write a function that accepts a Zod schema as an input, it's tempting to try something like this:

function inferSchema<T>(schema: z.ZodType<T>) {
  return schema;
}

This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of schema will be an instance of ZodType.

inferSchema(z.string());
// => ZodType<string>

This approach loses type information, namely which subclass the input actually is (in this case, ZodString). That means you can't call any string-specific methods like .min() on the result of inferSchema.

A better approach is to infer the schema as a whole instead of merely its inferred type. You can do this with a utility type called z.ZodTypeAny.

function inferSchema<T extends z.ZodTypeAny>(schema: T) {
  return schema;
}

inferSchema(z.string());
// => ZodString

ZodTypeAny is just a shorthand for ZodType<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.

Inferring the inferred type

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

Constraining allowable inputs

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>'

Error handling

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

Error formatting

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"]
}

Comparison

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.

Joi

https://github.com/hapijs/joi

Doesn't support static type inference 😕

Yup

https://github.com/jquense/yup

Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.

  * Supports casting and transforms
  * All object fields are optional by default
  * Missing promise schemas
  * Missing function schemas
  * Missing union & intersection schemas

io-ts

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.

  * Supports codecs with serialization & deserialization transforms
  * Supports branded types
  * Supports advanced functional programming, higher-kinded types, fp-ts compatibility
  * Missing object methods: (pick, omit, partial, deepPartial, merge, extend)
  * Missing nonempty arrays with proper typing ([T, ...T[]])
  * Missing promise schemas
  * Missing function schemas

Runtypes

https://github.com/pelotom/runtypes

Good type inference support.

  * Supports "pattern matching": computed properties that distribute over unions
  * Missing object methods: (deepPartial, merge)
  * Missing nonempty arrays with proper typing ([T, ...T[]])
  * Missing promise schemas
  * Missing error customization

Ow

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 (e.g. 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.

Changelog

View the changelog at CHANGELOG.md

TypeScript-first schema validation with static type inference
https://zod.dev/
colinhacks
2020-03-07T20:59:08Z
<div><div><article><p>
  <a href="https://github.com/colinhacks/zod/blob/main/logo.svg"></a>
  </p><p></p><h2>Zod</h2><a href="#zod"></a><p></p>
  <p>
    ✨ <a href="https://zod.dev">https://zod.dev</a> ✨
    <br/>
    TypeScript-first schema validation with static type inference
  </p>


<p>
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amain"></a>
<a href="https://twitter.com/colinhacks"></a>
<a href="https://opensource.org/licenses/MIT"></a>
<a href="https://www.npmjs.com/package/zod"></a>
<a href="https://www.npmjs.com/package/zod"></a>
</p>

<p><a href="https://go.clerk.com/hqN4rp7"></a></p>

<p></p><h2>Table of contents</h2><a href="#table-of-contents"></a><p></p>
<blockquote>
<p>These docs have been translated into <a href="https://github.com/colinhacks/zod/blob/main/README_ZH.md">Chinese</a>.</p>
</blockquote>
<ul>
<li><a href="#table-of-contents">Table of contents</a></li>
<li><a href="#introduction">Introduction</a>
<ul>
<li><a href="#sponsors">Sponsors</a>
<ul>
<li><a href="#platinum">Platinum</a></li>
<li><a href="#gold">Gold</a></li>
<li><a href="#silver">Silver</a></li>
<li><a href="#bronze">Bronze</a></li>
<li><a href="#copper">Copper</a></li>
</ul>
</li>
<li><a href="#ecosystem">Ecosystem</a>
<ul>
<li><a href="#resources">Resources</a></li>
<li><a href="#api-libraries">API libraries</a></li>
<li><a href="#form-integrations">Form integrations</a></li>
<li><a href="#zod-to-x">Zod to X</a></li>
<li><a href="#x-to-zod">X to Zod</a></li>
<li><a href="#mocking">Mocking</a></li>
<li><a href="#powered-by-zod">Powered by Zod</a></li>
<li><a href="#utilities-for-zod">Utilities for Zod</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#installation">Installation</a>
<ul>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#from-npm-nodebun">From <code>npm</code> (Node/Bun)</a></li>
<li><a href="#from-denolandx-deno">From <code>deno.land/x</code> (Deno)</a></li>
</ul>
</li>
<li><a href="#basic-usage">Basic usage</a></li>
<li><a href="#primitives">Primitives</a></li>
<li><a href="#coercion-for-primitives">Coercion for primitives</a></li>
<li><a href="#literals">Literals</a></li>
<li><a href="#strings">Strings</a>
<ul>
<li><a href="#datetimes">Datetimes</a></li>
<li><a href="#dates">Dates</a></li>
<li><a href="#times">Times</a></li>
<li><a href="#ip-addresses">IP addresses</a></li>
</ul>
</li>
<li><a href="#numbers">Numbers</a></li>
<li><a href="#bigints">BigInts</a></li>
<li><a href="#nans">NaNs</a></li>
<li><a href="#booleans">Booleans</a></li>
<li><a href="#dates">Dates</a></li>
<li><a href="#zod-enums">Zod enums</a></li>
<li><a href="#native-enums">Native enums</a></li>
<li><a href="#optionals">Optionals</a></li>
<li><a href="#nullables">Nullables</a></li>
<li><a href="#objects">Objects</a>
<ul>
<li><a href="#shape"><code>.shape</code></a></li>
<li><a href="#keyof"><code>.keyof</code></a></li>
<li><a href="#extend"><code>.extend</code></a></li>
<li><a href="#merge"><code>.merge</code></a></li>
<li><a href="#pickomit"><code>.pick/.omit</code></a></li>
<li><a href="#partial"><code>.partial</code></a></li>
<li><a href="#deeppartial"><code>.deepPartial</code></a></li>
<li><a href="#required"><code>.required</code></a></li>
<li><a href="#passthrough"><code>.passthrough</code></a></li>
<li><a href="#strict"><code>.strict</code></a></li>
<li><a href="#strip"><code>.strip</code></a></li>
<li><a href="#catchall"><code>.catchall</code></a></li>
</ul>
</li>
<li><a href="#arrays">Arrays</a>
<ul>
<li><a href="#element"><code>.element</code></a></li>
<li><a href="#nonempty"><code>.nonempty</code></a></li>
<li><a href="#minmaxlength"><code>.min/.max/.length</code></a></li>
</ul>
</li>
<li><a href="#tuples">Tuples</a></li>
<li><a href="#unions">Unions</a></li>
<li><a href="#discriminated-unions">Discriminated unions</a></li>
<li><a href="#records">Records</a>
<ul>
<li><a href="#record-key-type">Record key type</a></li>
</ul>
</li>
<li><a href="#maps">Maps</a></li>
<li><a href="#sets">Sets</a></li>
<li><a href="#intersections">Intersections</a></li>
<li><a href="#recursive-types">Recursive types</a>
<ul>
<li><a href="#zodtype-with-zodeffects">ZodType with ZodEffects</a></li>
<li><a href="#json-type">JSON type</a></li>
<li><a href="#cyclical-objects">Cyclical objects</a></li>
</ul>
</li>
<li><a href="#promises">Promises</a></li>
<li><a href="#instanceof">Instanceof</a></li>
<li><a href="#functions">Functions</a></li>
<li><a href="#preprocess">Preprocess</a></li>
<li><a href="#custom-schemas">Custom schemas</a></li>
<li><a href="#schema-methods">Schema methods</a>
<ul>
<li><a href="#parse"><code>.parse</code></a></li>
<li><a href="#parseasync"><code>.parseAsync</code></a></li>
<li><a href="#safeparse"><code>.safeParse</code></a></li>
<li><a href="#safeparseasync"><code>.safeParseAsync</code></a></li>
<li><a href="#refine"><code>.refine</code></a>
<ul>
<li><a href="#arguments">Arguments</a></li>
<li><a href="#customize-error-path">Customize error path</a></li>
<li><a href="#asynchronous-refinements">Asynchronous refinements</a></li>
<li><a href="#relationship-to-transforms">Relationship to transforms</a></li>
</ul>
</li>
<li><a href="#superrefine"><code>.superRefine</code></a>
<ul>
<li><a href="#abort-early">Abort early</a></li>
<li><a href="#type-refinements">Type refinements</a></li>
</ul>
</li>
<li><a href="#transform"><code>.transform</code></a>
<ul>
<li><a href="#chaining-order">Chaining order</a></li>
<li><a href="#validating-during-transform">Validating during transform</a></li>
<li><a href="#relationship-to-refinements">Relationship to refinements</a></li>
<li><a href="#async-transforms">Async transforms</a></li>
</ul>
</li>
<li><a href="#default"><code>.default</code></a></li>
<li><a href="#describe"><code>.describe</code></a></li>
<li><a href="#catch"><code>.catch</code></a></li>
<li><a href="#optional"><code>.optional</code></a></li>
<li><a href="#nullable"><code>.nullable</code></a></li>
<li><a href="#nullish"><code>.nullish</code></a></li>
<li><a href="#array"><code>.array</code></a></li>
<li><a href="#promise"><code>.promise</code></a></li>
<li><a href="#or"><code>.or</code></a></li>
<li><a href="#and"><code>.and</code></a></li>
<li><a href="#brand"><code>.brand</code></a></li>
<li><a href="#readonly"><code>.readonly</code></a></li>
<li><a href="#pipe"><code>.pipe</code></a>
<ul>
<li><a href="#you-can-use-pipe-to-fix-common-issues-with-zcoerce">You can use <code>.pipe()</code> to fix common issues with <code>z.coerce</code>.</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#guides-and-concepts">Guides and concepts</a>
<ul>
<li><a href="#type-inference">Type inference</a></li>
<li><a href="#writing-generic-functions">Writing generic functions</a>
<ul>
<li><a href="#constraining-allowable-inputs">Constraining allowable inputs</a></li>
</ul>
</li>
<li><a href="#error-handling">Error handling</a></li>
<li><a href="#error-formatting">Error formatting</a></li>
</ul>
</li>
<li><a href="#comparison">Comparison</a>
<ul>
<li><a href="#joi">Joi</a></li>
<li><a href="#yup">Yup</a></li>
<li><a href="#io-ts">io-ts</a></li>
<li><a href="#runtypes">Runtypes</a></li>
<li><a href="#ow">Ow</a></li>
</ul>
</li>
<li><a href="#changelog">Changelog</a></li>
</ul>
<p></p><h2>Introduction</h2><a href="#introduction"></a><p></p>
<p>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 <code>string</code> to a complex nested object.</p>
<p>Zod is designed to be as developer-friendly as possible. The goal is to eliminate duplicative type declarations. With Zod, you declare a validator <em>once</em> and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.</p>
<p>Some other great aspects:</p>
<ul>
<li>Zero dependencies</li>
<li>Works in Node.js and all modern browsers</li>
<li>Tiny: 8kb minified + zipped</li>
<li>Immutable: methods (e.g. <code>.optional()</code>) return a new instance</li>
<li>Concise, chainable interface</li>
<li>Functional approach: <a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">parse, don't validate</a></li>
<li>Works with plain JavaScript too! You don't need to use TypeScript.</li>
</ul>
<p></p><h2>Sponsors</h2><a href="#sponsors"></a><p></p>
<p>Sponsorship at any level is appreciated and encouraged. If you built a paid product using Zod, consider one of the <a href="https://github.com/sponsors/colinhacks">corporate tiers</a>.</p>

<p></p><h3>Diamond</h3><a href="#diamond"></a><p></p>
<br/>
<div>
  <a href="https://go.clerk.com/PKHrcwh">
    
  </a>
  <p>
    The most comprehensive User Management Platform
    <br/>
    <a href="https://go.clerk.com/PKHrcwh">clerk.com</a>
  </p>
</div>
<p></p><h3>Platinum</h3><a href="#platinum"></a><p></p>


<p></p><h3>Gold</h3><a href="#gold"></a><p></p>


<p></p><h3>Silver</h3><a href="#silver"></a><p></p>

<p></p><h3>Bronze</h3><a href="#bronze"></a><p></p>

<p></p><h3>Ecosystem</h3><a href="#ecosystem"></a><p></p>
<p>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 <a href="https://twitter.com/colinhacks">on Twitter</a> or <a href="https://github.com/colinhacks/zod/discussions">start a Discussion</a>. I'll add it below and tweet it out.</p>
<p></p><h4>Resources</h4><a href="#resources"></a><p></p>
<ul>
<li><a href="https://www.totaltypescript.com/tutorials/zod">Total TypeScript Zod Tutorial</a> by <a href="https://twitter.com/mattpocockuk">@mattpocockuk</a></li>
<li><a href="https://www.youtube.com/watch?v=rY_XqfSHock">Fixing TypeScript's Blindspot: Runtime Typechecking</a> by <a href="https://twitter.com/jherr">@jherr</a></li>
</ul>
<p></p><h4>API libraries</h4><a href="#api-libraries"></a><p></p>
<ul>
<li><a href="https://github.com/trpc/trpc"><code>tRPC</code></a>: Build end-to-end typesafe APIs without GraphQL.</li>
<li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-nestjs"><code>@anatine/zod-nestjs</code></a>: Helper methods for using Zod in a NestJS project.</li>
<li><a href="https://github.com/flock-community/zod-endpoints"><code>zod-endpoints</code></a>: Contract-first strictly typed endpoints with Zod. OpenAPI compatible.</li>
<li><a href="https://github.com/evertdespiegeleer/zhttp"><code>zhttp</code></a>: An OpenAPI compatible, strictly typed http library with Zod input and response validation.</li>
<li><a href="https://github.com/SeasonedSoftware/domain-functions/"><code>domain-functions</code></a>: Decouple your business logic from your framework using composable functions. With first-class type inference from end to end powered by Zod schemas.</li>
<li><a href="https://github.com/ecyrbe/zodios"><code>@zodios/core</code></a>: A typescript API client with runtime and compile time validation backed by axios and zod.</li>
<li><a href="https://github.com/RobinTail/express-zod-api"><code>express-zod-api</code></a>: Build Express-based APIs with I/O schema validation and custom middlewares.</li>
<li><a href="https://github.com/sumukhbarve/monoduck/blob/main/src/tapiduck/README.md"><code>tapiduck</code></a>: End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler.</li>
<li><a href="https://github.com/JakeFenley/koa-zod-router"><code>koa-zod-router</code></a>: Create typesafe routes in Koa with I/O validation using Zod.</li>
<li><a href="https://github.com/RobinTail/zod-sockets"><code>zod-sockets</code></a>: Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs</li>
</ul>
<p></p><h4>Form integrations</h4><a href="#form-integrations"></a><p></p>
<ul>
<li><a href="https://github.com/react-hook-form/resolvers#zod"><code>react-hook-form</code></a>: A first-party Zod resolver for React Hook Form.</li>
<li><a href="https://github.com/causaly/zod-validation-error"><code>zod-validation-error</code></a>: Generate user-friendly error messages from <code>ZodError</code>s.</li>
<li><a href="https://github.com/robertLichtnow/zod-formik-adapter"><code>zod-formik-adapter</code></a>: A community-maintained Formik adapter for Zod.</li>
<li><a href="https://github.com/esamattis/react-zorm"><code>react-zorm</code></a>: Standalone <code>&lt;form&gt;</code> generation and validation for React using Zod.</li>
<li><a href="https://github.com/rileytomasek/zodix"><code>zodix</code></a>: Zod utilities for FormData and URLSearchParams in Remix loaders and actions.</li>
<li><a href="https://conform.guide/api/zod/parseWithZod"><code>conform</code></a>: A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js.</li>
<li><a href="https://github.com/kiliman/remix-params-helper"><code>remix-params-helper</code></a>: Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.</li>
<li><a href="https://github.com/glazy/formik-validator-zod"><code>formik-validator-zod</code></a>: Formik-compliant validator library that simplifies using Zod with Formik.</li>
<li><a href="https://github.com/aiji42/zod-i18n"><code>zod-i18n-map</code></a>: Useful for translating Zod error messages.</li>
<li><a href="https://github.com/fabian-hiller/modular-forms"><code>@modular-forms/solid</code></a>: Modular form library for SolidJS that supports Zod for validation.</li>
<li><a href="https://github.com/crutchcorn/houseform/"><code>houseform</code></a>: A React form library that uses Zod for validation.</li>
<li><a href="https://github.com/ciscoheat/sveltekit-superforms"><code>sveltekit-superforms</code></a>: Supercharged form library for SvelteKit with Zod validation.</li>
<li><a href="https://github.com/MonoidDev/mobx-zod-form"><code>mobx-zod-form</code></a>: Data-first form builder based on MobX &amp; Zod.</li>
<li><a href="https://github.com/logaretm/vee-validate/tree/main/packages/zod"><code>@vee-validate/zod</code></a>: Form library for Vue.js with Zod schema validation.</li>
</ul>
<p></p><h4>Zod to X</h4><a href="#zod-to-x"></a><p></p>
<ul>
<li><a href="https://github.com/sachinraja/zod-to-ts"><code>zod-to-ts</code></a>: Generate TypeScript definitions from Zod schemas.</li>
<li><a href="https://github.com/StefanTerdell/zod-to-json-schema"><code>zod-to-json-schema</code></a>: Convert your Zod schemas into <a href="https://json-schema.org/">JSON Schemas</a>.</li>
<li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi"><code>@anatine/zod-openapi</code></a>: Converts a Zod schema to an OpenAPI v3.x <code>SchemaObject</code>.</li>
<li><a href="https://github.com/DavidTimms/zod-fast-check"><code>zod-fast-check</code></a>: Generate <code>fast-check</code> arbitraries from Zod schemas.</li>
<li><a href="https://github.com/kbkk/abitia/tree/main/packages/zod-dto"><code>zod-dto</code></a>: Generate Nest.js DTOs from a Zod schema.</li>
<li><a href="https://github.com/turkerdev/fastify-type-provider-zod"><code>fastify-type-provider-zod</code></a>: Create Fastify type providers from Zod schemas.</li>
<li><a href="https://github.com/asteasolutions/zod-to-openapi"><code>zod-to-openapi</code></a>: Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints &amp; parameters.</li>
<li><a href="https://github.com/incetarik/nestjs-graphql-zod"><code>nestjs-graphql-zod</code></a>: Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.</li>
<li><a href="https://github.com/samchungy/zod-openapi"><code>zod-openapi</code></a>: Create full OpenAPI v3.x documentation from Zod schemas.</li>
<li><a href="https://github.com/samchungy/fastify-zod-openapi"><code>fastify-zod-openapi</code></a>: Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas.</li>
<li><a href="https://typeschema.com/"><code>typeschema</code></a>: Universal adapter for schema validation.</li>
</ul>
<p></p><h4>X to Zod</h4><a href="#x-to-zod"></a><p></p>
<ul>
<li><a href="https://github.com/fabien0102/ts-to-zod"><code>ts-to-zod</code></a>: Convert TypeScript definitions into Zod schemas.</li>
<li><a href="https://github.com/johngeorgewright/runtyping/tree/main/packages/zod"><code>@runtyping/zod</code></a>: Generate Zod from static types &amp; JSON schema.</li>
<li><a href="https://github.com/StefanTerdell/json-schema-to-zod"><code>json-schema-to-zod</code></a>: Convert your <a href="https://json-schema.org/">JSON Schemas</a> into Zod schemas. <a href="https://StefanTerdell.github.io/json-schema-to-zod-react/">Live demo</a>.</li>
<li><a href="https://github.com/rsinohara/json-to-zod"><code>json-to-zod</code></a>: Convert JSON objects into Zod schemas. <a href="https://rsinohara.github.io/json-to-zod-react/">Live demo</a>.</li>
<li><a href="https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema"><code>graphql-codegen-typescript-validation-schema</code></a>: GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.</li>
<li><a href="https://github.com/CarterGrimmeisen/zod-prisma"><code>zod-prisma</code></a>: Generate Zod schemas from your Prisma schema.</li>
<li><a href="https://github.com/Southclaws/supervillain"><code>Supervillain</code></a>: Generate Zod schemas from your Go structs.</li>
<li><a href="https://github.com/omar-dulaimi/prisma-zod-generator"><code>prisma-zod-generator</code></a>: Emit Zod schemas from your Prisma schema.</li>
<li><a href="https://orm.drizzle.team/docs/zod"><code>drizzle-zod</code></a>: Emit Zod schemas from your Drizzle schema.</li>
<li><a href="https://github.com/omar-dulaimi/prisma-trpc-generator"><code>prisma-trpc-generator</code></a>: Emit fully implemented tRPC routers and their validation schemas using Zod.</li>
<li><a href="https://github.com/chrishoermann/zod-prisma-types"><code>zod-prisma-types</code></a> Create Zod types from your Prisma models.</li>
<li><a href="https://app.quicktype.io/"><code>quicktype</code></a>: Convert JSON objects and JSON schemas into Zod schemas.</li>
<li><a href="https://github.com/saiichihashimoto/sanity-typed/tree/main/packages/zod"><code>@sanity-typed/zod</code></a>: Generate Zod Schemas from <a href="https://www.sanity.io/docs/schema-types">Sanity Schemas</a>.</li>
<li><a href="https://github.com/ivangreene/java-to-zod"><code>java-to-zod</code></a>: Convert POJOs to Zod schemas</li>
<li><a href="https://github.com/anymaniax/orval"><code>Orval</code></a>: Generate Zod schemas from OpenAPI schemas</li>
<li><a href="https://github.com/kubb-labs/kubb"><code>Kubb</code></a>: Generate SDKs and Zod schemas from your OpenAPI schemas</li>
</ul>
<p></p><h4>Mocking</h4><a href="#mocking"></a><p></p>
<ul>
<li><a href="https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock"><code>@anatine/zod-mock</code></a>: Generate mock data from a Zod schema. Powered by <a href="https://github.com/faker-js/faker">faker.js</a>.</li>
<li><a href="https://github.com/dipasqualew/zod-mocking"><code>zod-mocking</code></a>: Generate mock data from your Zod schemas.</li>
<li><a href="https://github.com/timdeschryver/zod-fixture"><code>zod-fixture</code></a>: Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.</li>
<li><a href="https://zocker.sigrist.dev"><code>zocker</code></a>: Generate plausible mock-data from your schemas.</li>
<li><a href="https://github.com/ItMaga/zodock"><code>zodock</code></a> Generate mock data based on Zod schemas.</li>
<li><a href="https://github.com/soc221b/zod-schema-faker"><code>zod-schema-faker</code></a> Generates mock data from Zod schemas. Powered by <a href="https://github.com/faker-js/faker">@faker-js/faker</a> and <a href="https://github.com/fent/randexp.js">randexp.js</a></li>
</ul>
<p></p><h4>Powered by Zod</h4><a href="#powered-by-zod"></a><p></p>
<ul>
<li><a href="https://github.com/JacobWeisenburger/freerstore"><code>freerstore</code></a>: Firestore cost optimizer.</li>
<li><a href="https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference"><code>slonik</code></a>: Node.js Postgres client with strong Zod integration.</li>
<li><a href="https://github.com/mdbetancourt/soly"><code>soly</code></a>: Create CLI applications with zod.</li>
<li><a href="https://github.com/vadimdemedes/pastel"><code>pastel</code></a>: Create CLI applications with react, zod, and ink.</li>
<li><a href="https://github.com/sidwebworks/zod-xlsx"><code>zod-xlsx</code></a>: A xlsx based resource validator using Zod schemas.</li>
<li><a href="https://github.com/lostfictions/znv"><code>znv</code></a>: Type-safe environment parsing and validation for Node.js with Zod schemas.</li>
<li><a href="https://github.com/alexmarqs/zod-config"><code>zod-config</code></a>: Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.</li>
</ul>
<p></p><h4>Utilities for Zod</h4><a href="#utilities-for-zod"></a><p></p>
<ul>
<li><a href="https://github.com/JacobWeisenburger/zod_utilz"><code>zod_utilz</code></a>: Framework agnostic utilities for Zod.</li>
<li><a href="https://github.com/marilari88/zod-playground"><code>zod-playground</code></a>: A tool for learning and testing Zod schema validation functionalities. <a href="https://zod-playground.vercel.app/">Link</a>.</li>
<li><a href="https://github.com/nereumelo/zod-sandbox"><code>zod-sandbox</code></a>: Controlled environment for testing zod schemas. <a href="https://zod-sandbox.vercel.app/">Live demo</a>.</li>
<li><a href="https://github.com/schalkventer/zod-dev"><code>zod-dev</code></a>: Conditionally disables Zod runtime parsing in production.</li>
<li><a href="https://github.com/duplojs/duplojs-zod-accelerator"><code>zod-accelerator</code></a>: Accelerates Zod's throughput up to ~100x.</li>
</ul>
<p></p><h2>Installation</h2><a href="#installation"></a><p></p>
<p></p><h3>Requirements</h3><a href="#requirements"></a><p></p>
<ul>
<li>
<p>TypeScript 4.5+!</p>
</li>
<li>
<p>You must enable <code>strict</code> mode in your <code>tsconfig.json</code>. This is a best practice for all TypeScript projects.</p>
<div><pre><span>// tsconfig.json</span>
<span>{</span>
  <span>// ...</span>
  <span>"compilerOptions"</span>: <span>{</span>
    <span>// ...</span>
    <span>"strict"</span>: <span>true</span>
  <span>}</span>
<span>}</span></pre></div>
</li>
</ul>
<p></p><h3>From <code>npm</code> (Node/Bun)</h3><a href="#from-npm-nodebun"></a><p></p>
<div><pre>npm install zod       <span><span>#</span> npm</span>
yarn add zod          <span><span>#</span> yarn</span>
bun add zod           <span><span>#</span> bun</span>
pnpm add zod          <span><span>#</span> pnpm</span></pre></div>
<p>Zod also publishes a canary version on every commit. To install the canary:</p>
<div><pre>npm install zod@canary       <span><span>#</span> npm</span>
yarn add zod@canary          <span><span>#</span> yarn</span>
bun add zod@canary           <span><span>#</span> bun</span>
pnpm add zod@canary          <span><span>#</span> pnpm</span></pre></div>
<p></p><h3>From <code>deno.land/x</code> (Deno)</h3><a href="#from-denolandx-deno"></a><p></p>
<p>Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on <a href="https://deno.land/x">deno.land/x</a>. The latest version can be imported like so:</p>
<div><pre><span>import</span> <span>{</span> <span>z</span> <span>}</span> <span>from</span> <span>"https://deno.land/x/zod/mod.ts"</span><span>;</span></pre></div>
<p>You can also specify a particular version:</p>
<div><pre><span>import</span> <span>{</span> <span>z</span> <span>}</span> <span>from</span> <span>"https://deno.land/x/zod@v3.16.1/mod.ts"</span><span>;</span></pre></div>
<blockquote>
<p>The rest of this README assumes you are using npm and importing directly from the <code>"zod"</code> package.</p>
</blockquote>
<p></p><h2>Basic usage</h2><a href="#basic-usage"></a><p></p>
<p>Creating a simple string schema</p>
<div><pre><span>import</span> <span>{</span> <span>z</span> <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>// creating a schema for strings</span>
<span>const</span> <span>mySchema</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>

<span>// parsing</span>
<span>mySchema</span><span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span>
<span>mySchema</span><span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; throws ZodError</span>

<span>// "safe" parsing (doesn't throw error if validation fails)</span>
<span>mySchema</span><span>.</span><span>safeParse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; { success: true; data: "tuna" }</span>
<span>mySchema</span><span>.</span><span>safeParse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; { success: false; error: ZodError }</span></pre></div>
<p>Creating an object schema</p>
<div><pre><span>import</span> <span>{</span> <span>z</span> <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>const</span> <span>User</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>username</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>User</span><span>.</span><span>parse</span><span>(</span><span>{</span> <span>username</span>: <span>"Ludwig"</span> <span>}</span><span>)</span><span>;</span>

<span>// extract the inferred type</span>
<span>type</span> <span>User</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>User</span><span>&gt;</span><span>;</span>
<span>// { username: string }</span></pre></div>
<p></p><h2>Primitives</h2><a href="#primitives"></a><p></p>
<div><pre><span>import</span> <span>{</span> <span>z</span> <span>}</span> <span>from</span> <span>"zod"</span><span>;</span>

<span>// primitive values</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>symbol</span><span>(</span><span>)</span><span>;</span>

<span>// empty types</span>
<span>z</span><span>.</span><span>undefined</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>null</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>void</span><span>(</span><span>)</span><span>;</span> <span>// accepts undefined</span>

<span>// catch-all types</span>
<span>// allows any value</span>
<span>z</span><span>.</span><span>any</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>unknown</span><span>(</span><span>)</span><span>;</span>

<span>// never type</span>
<span>// allows no values</span>
<span>z</span><span>.</span><span>never</span><span>(</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Coercion for primitives</h2><a href="#coercion-for-primitives"></a><p></p>
<p>Zod now provides a more convenient way to coerce primitive values.</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>coerce</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; "12"</span></pre></div>
<p>During the parsing step, the input is passed through the <code>String()</code> function, which is a JavaScript built-in for coercing data into strings.</p>
<div><pre><span>schema</span><span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// =&gt; "12"</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>true</span><span>)</span><span>;</span> <span>// =&gt; "true"</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; "undefined"</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; "null"</span></pre></div>
<p>The returned schema is a normal <code>ZodString</code> instance so you can use all string methods.</p>
<div><pre><span>z</span><span>.</span><span>coerce</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span></pre></div>
<p><strong>How coercion works</strong></p>
<p>All primitive types support coercion. Zod coerces all inputs using the built-in constructors: <code>String(input)</code>, <code>Number(input)</code>, <code>new Date(input)</code>, etc.</p>
<div><pre><span>z</span><span>.</span><span>coerce</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span> <span>// String(input)</span>
<span>z</span><span>.</span><span>coerce</span><span>.</span><span>number</span><span>(</span><span>)</span><span>;</span> <span>// Number(input)</span>
<span>z</span><span>.</span><span>coerce</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span> <span>// Boolean(input)</span>
<span>z</span><span>.</span><span>coerce</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span> <span>// BigInt(input)</span>
<span>z</span><span>.</span><span>coerce</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span> <span>// new Date(input)</span></pre></div>
<p><strong>Note</strong> — Boolean coercion with <code>z.coerce.boolean()</code> may not work how you expect. Any <a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">truthy</a> value is coerced to <code>true</code>, and any <a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">falsy</a> value is coerced to <code>false</code>.</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>coerce</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>;</span> <span>// Boolean(input)</span>

<span>schema</span><span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>"true"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>"false"</span><span>)</span><span>;</span> <span>// =&gt; true</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>1</span><span>)</span><span>;</span> <span>// =&gt; true</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>[</span><span>]</span><span>)</span><span>;</span> <span>// =&gt; true</span>

<span>schema</span><span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// =&gt; false</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>""</span><span>)</span><span>;</span> <span>// =&gt; false</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; false</span>
<span>schema</span><span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; false</span></pre></div>
<p>For more control over coercion logic, consider using <a href="#preprocess"><code>z.preprocess</code></a> or <a href="#pipe"><code>z.pipe()</code></a>.</p>
<p></p><h2>Literals</h2><a href="#literals"></a><p></p>
<p>Literal schemas represent a <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types">literal type</a>, like <code>"hello world"</code> or <code>5</code>.</p>
<div><pre><span>const</span> <span>tuna</span> <span>=</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>
<span>const</span> <span>twelve</span> <span>=</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>12</span><span>)</span><span>;</span>
<span>const</span> <span>twobig</span> <span>=</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>2n</span><span>)</span><span>;</span> <span>// bigint literal</span>
<span>const</span> <span>tru</span> <span>=</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>true</span><span>)</span><span>;</span>

<span>const</span> <span>terrificSymbol</span> <span>=</span> <span>Symbol</span><span>(</span><span>"terrific"</span><span>)</span><span>;</span>
<span>const</span> <span>terrific</span> <span>=</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>terrificSymbol</span><span>)</span><span>;</span>

<span>// retrieve literal value</span>
<span>tuna</span><span>.</span><span>value</span><span>;</span> <span>// "tuna"</span></pre></div>
<blockquote>
<p>Currently there is no support for Date literals in Zod. If you have a use case for this feature, please file an issue.</p>
</blockquote>
<p></p><h2>Strings</h2><a href="#strings"></a><p></p>
<p>Zod includes a handful of string-specific validations.</p>
<div><pre><span>// validations</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>emoji</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>uuid</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nanoid</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>cuid</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>cuid2</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ulid</span><span>(</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>regex</span><span>(</span><span>regex</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>includes</span><span>(</span><span>string</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>startsWith</span><span>(</span><span>string</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>endsWith</span><span>(</span><span>string</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>)</span><span>;</span> <span>// ISO 8601; by default only `Z` timezone allowed</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>)</span><span>;</span> <span>// defaults to allow both IPv4 and IPv6</span>

<span>// transforms</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>trim</span><span>(</span><span>)</span><span>;</span> <span>// trim whitespace</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>toLowerCase</span><span>(</span><span>)</span><span>;</span> <span>// toLowerCase</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>toUpperCase</span><span>(</span><span>)</span><span>;</span> <span>// toUpperCase</span>

<span>// added in Zod 3.23</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span> <span>// ISO date format (YYYY-MM-DD)</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>)</span><span>;</span> <span>// ISO time format (HH:mm:ss[.SSSSSS])</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>duration</span><span>(</span><span>)</span><span>;</span> <span>// ISO 8601 duration</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>base64</span><span>(</span><span>)</span><span>;</span></pre></div>
<blockquote>
<p>Check out <a href="https://github.com/validatorjs/validator.js">validator.js</a> for a bunch of other useful string validation functions that can be used in conjunction with <a href="#refine">Refinements</a>.</p>
</blockquote>
<p>You can customize some common error messages when creating a string schema.</p>
<div><pre><span>const</span> <span>name</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>{</span>
  <span>required_error</span>: <span>"Name is required"</span><span>,</span>
  <span>invalid_type_error</span>: <span>"Name must be a string"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>When using validation methods, you can pass in an additional argument to provide a custom error message.</p>
<div><pre><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>,</span> <span>{</span> <span>message</span>: <span>"Must be 5 or more characters long"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>,</span> <span>{</span> <span>message</span>: <span>"Must be 5 or fewer characters long"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>,</span> <span>{</span> <span>message</span>: <span>"Must be exactly 5 characters long"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>email</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid email address"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid url"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>emoji</span><span>(</span><span>{</span> <span>message</span>: <span>"Contains non-emoji characters"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>uuid</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid UUID"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>includes</span><span>(</span><span>"tuna"</span><span>,</span> <span>{</span> <span>message</span>: <span>"Must include tuna"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>startsWith</span><span>(</span><span>"https://"</span><span>,</span> <span>{</span> <span>message</span>: <span>"Must provide secure URL"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>endsWith</span><span>(</span><span>".com"</span><span>,</span> <span>{</span> <span>message</span>: <span>"Only .com domains allowed"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid datetime string! Must be UTC."</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid date string!"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid time string!"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> <span>message</span>: <span>"Invalid IP address"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h3>Datetimes</h3><a href="#datetimes"></a><p></p>
<p>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.</p>
<p>The <code>z.string().datetime()</code> method enforces ISO 8601; default is no timezone offsets and arbitrary sub-second decimal precision.</p>
<div><pre><span>const</span> <span>datetime</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>)</span><span>;</span>

<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// pass</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123Z"</span><span>)</span><span>;</span> <span>// pass</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123456Z"</span><span>)</span><span>;</span> <span>// pass (arbitrary precision)</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00+02:00"</span><span>)</span><span>;</span> <span>// fail (no offsets allowed)</span></pre></div>
<p>Timezone offsets can be allowed by setting the <code>offset</code> option to <code>true</code>.</p>
<div><pre><span>const</span> <span>datetime</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> <span>offset</span>: <span>true</span> <span>}</span><span>)</span><span>;</span>

<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00+02:00"</span><span>)</span><span>;</span> <span>// pass</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+02:00"</span><span>)</span><span>;</span> <span>// pass (millis optional)</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+0200"</span><span>)</span><span>;</span> <span>// pass (millis optional)</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123+02"</span><span>)</span><span>;</span> <span>// pass (only offset hours)</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// pass (Z still supported)</span></pre></div>
<p>You can additionally constrain the allowable <code>precision</code>. By default, arbitrary sub-second precision is supported (but optional).</p>
<div><pre><span>const</span> <span>datetime</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>datetime</span><span>(</span><span>{</span> <span>precision</span>: <span>3</span> <span>}</span><span>)</span><span>;</span>

<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123Z"</span><span>)</span><span>;</span> <span>// pass</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00Z"</span><span>)</span><span>;</span> <span>// fail</span>
<span>datetime</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01T00:00:00.123456Z"</span><span>)</span><span>;</span> <span>// fail</span></pre></div>
<p></p><h3>Dates</h3><a href="#dates"></a><p></p>
<blockquote>
<p>Added in Zod 3.23</p>
</blockquote>
<p>The <code>z.string().date()</code> method validates strings in the format <code>YYYY-MM-DD</code>.</p>
<div><pre><span>const</span> <span>date</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>

<span>date</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-01"</span><span>)</span><span>;</span> <span>// pass</span>
<span>date</span><span>.</span><span>parse</span><span>(</span><span>"2020-1-1"</span><span>)</span><span>;</span> <span>// fail</span>
<span>date</span><span>.</span><span>parse</span><span>(</span><span>"2020-01-32"</span><span>)</span><span>;</span> <span>// fail</span></pre></div>
<p></p><h3>Times</h3><a href="#times"></a><p></p>
<blockquote>
<p>Added in Zod 3.23</p>
</blockquote>
<p>The <code>z.string().time()</code> method validates strings in the format <code>HH:MM:SS[.s+]</code>. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind.</p>
<div><pre><span>const</span> <span>time</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>)</span><span>;</span>

<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00"</span><span>)</span><span>;</span> <span>// pass</span>
<span>time</span><span>.</span><span>parse</span><span>(</span><span>"09:52:31"</span><span>)</span><span>;</span> <span>// pass</span>
<span>time</span><span>.</span><span>parse</span><span>(</span><span>"23:59:59.9999999"</span><span>)</span><span>;</span> <span>// pass (arbitrary precision)</span>

<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00.123Z"</span><span>)</span><span>;</span> <span>// fail (no `Z` allowed)</span>
<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00.123+02:00"</span><span>)</span><span>;</span> <span>// fail (no offsets allowed)</span></pre></div>
<p>You can set the <code>precision</code> option to constrain the allowable decimal precision.</p>
<div><pre><span>const</span> <span>time</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>time</span><span>(</span><span>{</span> <span>precision</span>: <span>3</span> <span>}</span><span>)</span><span>;</span>

<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00.123"</span><span>)</span><span>;</span> <span>// pass</span>
<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00.123456"</span><span>)</span><span>;</span> <span>// fail</span>
<span>time</span><span>.</span><span>parse</span><span>(</span><span>"00:00:00"</span><span>)</span><span>;</span> <span>// fail</span></pre></div>
<p></p><h3>IP addresses</h3><a href="#ip-addresses"></a><p></p>
<p>The <code>z.string().ip()</code> method by default validate IPv4 and IPv6.</p>
<div><pre><span>const</span> <span>ip</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>)</span><span>;</span>

<span>ip</span><span>.</span><span>parse</span><span>(</span><span>"192.168.1.1"</span><span>)</span><span>;</span> <span>// pass</span>
<span>ip</span><span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// pass</span>
<span>ip</span><span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:192.168.1.1"</span><span>)</span><span>;</span> <span>// pass</span>

<span>ip</span><span>.</span><span>parse</span><span>(</span><span>"256.1.1.1"</span><span>)</span><span>;</span> <span>// fail</span>
<span>ip</span><span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:gggg:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// fail</span></pre></div>
<p>You can additionally set the IP <code>version</code>.</p>
<div><pre><span>const</span> <span>ipv4</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> <span>version</span>: <span>"v4"</span> <span>}</span><span>)</span><span>;</span>
<span>ipv4</span><span>.</span><span>parse</span><span>(</span><span>"84d5:51a0:9114:1855:4cfa:f2d7:1f12:7003"</span><span>)</span><span>;</span> <span>// fail</span>

<span>const</span> <span>ipv6</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>ip</span><span>(</span><span>{</span> <span>version</span>: <span>"v6"</span> <span>}</span><span>)</span><span>;</span>
<span>ipv6</span><span>.</span><span>parse</span><span>(</span><span>"192.168.1.1"</span><span>)</span><span>;</span> <span>// fail</span></pre></div>
<p></p><h2>Numbers</h2><a href="#numbers"></a><p></p>
<p>You can customize certain error messages when creating a number schema.</p>
<div><pre><span>const</span> <span>age</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>{</span>
  <span>required_error</span>: <span>"Age is required"</span><span>,</span>
  <span>invalid_type_error</span>: <span>"Age must be a number"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>Zod includes a handful of number-specific validations.</p>
<div><pre><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>gt</span><span>(</span><span>5</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>gte</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// alias .min(5)</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lt</span><span>(</span><span>5</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// alias .max(5)</span>

<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>int</span><span>(</span><span>)</span><span>;</span> <span>// value must be an integer</span>

<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>positive</span><span>(</span><span>)</span><span>;</span> <span>//     &gt; 0</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>nonnegative</span><span>(</span><span>)</span><span>;</span> <span>//  &gt;= 0</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>negative</span><span>(</span><span>)</span><span>;</span> <span>//     &lt; 0</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>nonpositive</span><span>(</span><span>)</span><span>;</span> <span>//  &lt;= 0</span>

<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>multipleOf</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// Evenly divisible by 5. Alias .step(5)</span>

<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>finite</span><span>(</span><span>)</span><span>;</span> <span>// value must be finite, not Infinity or -Infinity</span>
<span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>safe</span><span>(</span><span>)</span><span>;</span> <span>// value must be between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER</span></pre></div>
<p>Optionally, you can pass in a second argument to provide a custom error message.</p>
<div><pre><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5</span><span>,</span> <span>{</span> <span>message</span>: <span>"this👏is👏too👏big"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h2>BigInts</h2><a href="#bigints"></a><p></p>
<p>Zod includes a handful of bigint-specific validations.</p>
<div><pre><span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>gt</span><span>(</span><span>5n</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>gte</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// alias `.min(5n)`</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>lt</span><span>(</span><span>5n</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>lte</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// alias `.max(5n)`</span>

<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>positive</span><span>(</span><span>)</span><span>;</span> <span>// &gt; 0n</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>nonnegative</span><span>(</span><span>)</span><span>;</span> <span>// &gt;= 0n</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>negative</span><span>(</span><span>)</span><span>;</span> <span>// &lt; 0n</span>
<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>nonpositive</span><span>(</span><span>)</span><span>;</span> <span>// &lt;= 0n</span>

<span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>multipleOf</span><span>(</span><span>5n</span><span>)</span><span>;</span> <span>// Evenly divisible by 5n.</span></pre></div>
<p></p><h2>NaNs</h2><a href="#nans"></a><p></p>
<p>You can customize certain error messages when creating a nan schema.</p>
<div><pre><span>const</span> <span>isNaN</span> <span>=</span> <span>z</span><span>.</span><span>nan</span><span>(</span><span>{</span>
  <span>required_error</span>: <span>"isNaN is required"</span><span>,</span>
  <span>invalid_type_error</span>: <span>"isNaN must be 'not a number'"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Booleans</h2><a href="#booleans"></a><p></p>
<p>You can customize certain error messages when creating a boolean schema.</p>
<div><pre><span>const</span> <span>isActive</span> <span>=</span> <span>z</span><span>.</span><span>boolean</span><span>(</span><span>{</span>
  <span>required_error</span>: <span>"isActive is required"</span><span>,</span>
  <span>invalid_type_error</span>: <span>"isActive must be a boolean"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Dates</h2><a href="#dates-1"></a><p></p>
<p>Use z.date() to validate <code>Date</code> instances.</p>
<div><pre><span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>safeParse</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// success: true</span>
<span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>safeParse</span><span>(</span><span>"2022-01-12T00:00:00.000Z"</span><span>)</span><span>;</span> <span>// success: false</span></pre></div>
<p>You can customize certain error messages when creating a date schema.</p>
<div><pre><span>const</span> <span>myDateSchema</span> <span>=</span> <span>z</span><span>.</span><span>date</span><span>(</span><span>{</span>
  <span>required_error</span>: <span>"Please select a date and time"</span><span>,</span>
  <span>invalid_type_error</span>: <span>"That's not a date!"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>Zod provides a handful of date-specific validations.</p>
<div><pre><span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>"1900-01-01"</span><span>)</span><span>,</span> <span>{</span> <span>message</span>: <span>"Too old"</span> <span>}</span><span>)</span><span>;</span>
<span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>)</span><span>,</span> <span>{</span> <span>message</span>: <span>"Too young!"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p><strong>Coercion to Date</strong></p>
<p>Since <a href="https://github.com/colinhacks/zod/releases/tag/v3.20">zod 3.20</a>, use <a href="#coercion-for-primitives"><code>z.coerce.date()</code></a> to pass the input through <code>new Date(input)</code>.</p>
<div><pre><span>const</span> <span>dateSchema</span> <span>=</span> <span>z</span><span>.</span><span>coerce</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>DateSchema</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>dateSchema</span><span>&gt;</span><span>;</span>
<span>// type DateSchema = Date</span>

<span>/* valid dates */</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"2023-01-10T00:00:00.000Z"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"2023-01-10"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"1/10/23"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>new</span> <span>Date</span><span>(</span><span>"1/10/23"</span><span>)</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>

<span>/* invalid dates */</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"2023-13-10"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// false</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>dateSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"0000-00-00"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// false</span></pre></div>
<p>For older zod versions, use <a href="#preprocess"><code>z.preprocess</code></a> like <a href="https://github.com/colinhacks/zod/discussions/879#discussioncomment-2036276">described in this thread</a>.</p>
<p></p><h2>Zod enums</h2><a href="#zod-enums"></a><p></p>
<div><pre><span>const</span> <span>FishEnum</span> <span>=</span> <span>z</span><span>.</span><span>enum</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>type</span> <span>FishEnum</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>FishEnum</span><span>&gt;</span><span>;</span>
<span>// 'Salmon' | 'Tuna' | 'Trout'</span></pre></div>
<p><code>z.enum</code> is a Zod-native way to declare a schema with a fixed set of allowable <em>string</em> values. Pass the array of values directly into <code>z.enum()</code>. Alternatively, use <code>as const</code> to define your enum values as a tuple of strings. See the <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions">const assertion docs</a> for details.</p>
<div><pre><span>const</span> <span>VALUES</span> <span>=</span> <span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span> <span>as</span> <span>const</span><span>;</span>
<span>const</span> <span>FishEnum</span> <span>=</span> <span>z</span><span>.</span><span>enum</span><span>(</span><span>VALUES</span><span>)</span><span>;</span></pre></div>
<p>This is not allowed, since Zod isn't able to infer the exact values of each element.</p>
<div><pre><span>const</span> <span>fish</span> <span>=</span> <span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>;</span>
<span>const</span> <span>FishEnum</span> <span>=</span> <span>z</span><span>.</span><span>enum</span><span>(</span><span>fish</span><span>)</span><span>;</span></pre></div>
<p><strong><code>.enum</code></strong></p>
<p>To get autocompletion with a Zod enum, use the <code>.enum</code> property of your schema:</p>
<div><pre><span>FishEnum</span><span>.</span><span>enum</span><span>.</span><span>Salmon</span><span>;</span> <span>// =&gt; autocompletes</span>

<span>FishEnum</span><span>.</span><span>enum</span><span>;</span>
<span>/*</span>
<span>=&gt; {</span>
<span>  Salmon: "Salmon",</span>
<span>  Tuna: "Tuna",</span>
<span>  Trout: "Trout",</span>
<span>}</span>
<span>*/</span></pre></div>
<p>You can also retrieve the list of options as a tuple with the <code>.options</code> property:</p>
<div><pre><span>FishEnum</span><span>.</span><span>options</span><span>;</span> <span>// ["Salmon", "Tuna", "Trout"];</span></pre></div>
<p><strong><code>.exclude/.extract()</code></strong></p>
<p>You can create subsets of a Zod enum with the <code>.exclude</code> and <code>.extract</code> methods.</p>
<div><pre><span>const</span> <span>FishEnum</span> <span>=</span> <span>z</span><span>.</span><span>enum</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Tuna"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>SalmonAndTrout</span> <span>=</span> <span>FishEnum</span><span>.</span><span>extract</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>TunaOnly</span> <span>=</span> <span>FishEnum</span><span>.</span><span>exclude</span><span>(</span><span>[</span><span>"Salmon"</span><span>,</span> <span>"Trout"</span><span>]</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Native enums</h2><a href="#native-enums"></a><p></p>
<p>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 <code>z.nativeEnum()</code>.</p>
<p><strong>Numeric enums</strong></p>
<div><pre><span>enum</span> <span>Fruits</span> <span>{</span>
  <span>Apple</span><span>,</span>
  <span>Banana</span><span>,</span>
<span>}</span>

<span>const</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>nativeEnum</span><span>(</span><span>Fruits</span><span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>FruitEnum</span><span>&gt;</span><span>;</span> <span>// Fruits</span>

<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>Fruits</span><span>.</span><span>Apple</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>Fruits</span><span>.</span><span>Banana</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>1</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>3</span><span>)</span><span>;</span> <span>// fails</span></pre></div>
<p><strong>String enums</strong></p>
<div><pre><span>enum</span> <span>Fruits</span> <span>{</span>
  <span>Apple</span> <span>=</span> <span>"apple"</span><span>,</span>
  <span>Banana</span> <span>=</span> <span>"banana"</span><span>,</span>
  <span>Cantaloupe</span><span>,</span> <span>// you can mix numerical and string enums</span>
<span>}</span>

<span>const</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>nativeEnum</span><span>(</span><span>Fruits</span><span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>FruitEnum</span><span>&gt;</span><span>;</span> <span>// Fruits</span>

<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>Fruits</span><span>.</span><span>Apple</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>Fruits</span><span>.</span><span>Cantaloupe</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"apple"</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"banana"</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>0</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"Cantaloupe"</span><span>)</span><span>;</span> <span>// fails</span></pre></div>
<p><strong>Const enums</strong></p>
<p>The <code>.nativeEnum()</code> function works for <code>as const</code> objects as well.  <code>as const</code> requires TypeScript 3.4+!</p>
<div><pre><span>const</span> <span>Fruits</span> <span>=</span> <span>{</span>
  <span>Apple</span>: <span>"apple"</span><span>,</span>
  <span>Banana</span>: <span>"banana"</span><span>,</span>
  <span>Cantaloupe</span>: <span>3</span><span>,</span>
<span>}</span> <span>as</span> <span>const</span><span>;</span>

<span>const</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>nativeEnum</span><span>(</span><span>Fruits</span><span>)</span><span>;</span>
<span>type</span> <span>FruitEnum</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>FruitEnum</span><span>&gt;</span><span>;</span> <span>// "apple" | "banana" | 3</span>

<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"apple"</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"banana"</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>3</span><span>)</span><span>;</span> <span>// passes</span>
<span>FruitEnum</span><span>.</span><span>parse</span><span>(</span><span>"Cantaloupe"</span><span>)</span><span>;</span> <span>// fails</span></pre></div>
<p>You can access the underlying object with the <code>.enum</code> property:</p>
<div><pre><span>FruitEnum</span><span>.</span><span>enum</span><span>.</span><span>Apple</span><span>;</span> <span>// "apple"</span></pre></div>
<p></p><h2>Optionals</h2><a href="#optionals"></a><p></p>
<p>You can make any schema optional with <code>z.optional()</code>. This wraps the schema in a <code>ZodOptional</code> instance and returns the result.</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>optional</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>schema</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; returns undefined</span>
<span>type</span> <span>A</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>schema</span><span>&gt;</span><span>;</span> <span>// string | undefined</span></pre></div>
<p>For convenience, you can also call the <code>.optional()</code> method on an existing schema.</p>
<div><pre><span>const</span> <span>user</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>username</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>type</span> <span>C</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>user</span><span>&gt;</span><span>;</span> <span>// { username?: string | undefined };</span></pre></div>
<p>You can extract the wrapped schema from a <code>ZodOptional</code> instance with <code>.unwrap()</code>.</p>
<div><pre><span>const</span> <span>stringSchema</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>const</span> <span>optionalString</span> <span>=</span> <span>stringSchema</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span>
<span>optionalString</span><span>.</span><span>unwrap</span><span>(</span><span>)</span> <span>===</span> <span>stringSchema</span><span>;</span> <span>// true</span></pre></div>
<p></p><h2>Nullables</h2><a href="#nullables"></a><p></p>
<p>Similarly, you can create nullable types with <code>z.nullable()</code>.</p>
<div><pre><span>const</span> <span>nullableString</span> <span>=</span> <span>z</span><span>.</span><span>nullable</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>nullableString</span><span>.</span><span>parse</span><span>(</span><span>"asdf"</span><span>)</span><span>;</span> <span>// =&gt; "asdf"</span>
<span>nullableString</span><span>.</span><span>parse</span><span>(</span><span>null</span><span>)</span><span>;</span> <span>// =&gt; null</span></pre></div>
<p>Or use the <code>.nullable()</code> method.</p>
<div><pre><span>const</span> <span>E</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span> <span>// equivalent to nullableString</span>
<span>type</span> <span>E</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>E</span><span>&gt;</span><span>;</span> <span>// string | null</span></pre></div>
<p>Extract the inner schema with <code>.unwrap()</code>.</p>
<div><pre><span>const</span> <span>stringSchema</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>const</span> <span>nullableString</span> <span>=</span> <span>stringSchema</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span>
<span>nullableString</span><span>.</span><span>unwrap</span><span>(</span><span>)</span> <span>===</span> <span>stringSchema</span><span>;</span> <span>// true</span></pre></div>
<p></p><h2>Objects</h2><a href="#objects"></a><p></p>
<div><pre><span>// all properties are required by default</span>
<span>const</span> <span>Dog</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>age</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>// extract the inferred type like this</span>
<span>type</span> <span>Dog</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>Dog</span><span>&gt;</span><span>;</span>

<span>// equivalent to:</span>
<span>type</span> <span>Dog</span> <span>=</span> <span>{</span>
  <span>name</span>: <span>string</span><span>;</span>
  <span>age</span>: <span>number</span><span>;</span>
<span>}</span><span>;</span></pre></div>
<p></p><h3><code>.shape</code></h3><a href="#shape"></a><p></p>
<p>Use <code>.shape</code> to access the schemas for a particular key.</p>
<div><pre><span>Dog</span><span>.</span><span>shape</span><span>.</span><span>name</span><span>;</span> <span>// =&gt; string schema</span>
<span>Dog</span><span>.</span><span>shape</span><span>.</span><span>age</span><span>;</span> <span>// =&gt; number schema</span></pre></div>
<p></p><h3><code>.keyof</code></h3><a href="#keyof"></a><p></p>
<p>Use <code>.keyof</code> to create a <code>ZodEnum</code> schema from the keys of an object schema.</p>
<div><pre><span>const</span> <span>keySchema</span> <span>=</span> <span>Dog</span><span>.</span><span>keyof</span><span>(</span><span>)</span><span>;</span>
<span>keySchema</span><span>;</span> <span>// ZodEnum&lt;["name", "age"]&gt;</span></pre></div>
<p></p><h3><code>.extend</code></h3><a href="#extend"></a><p></p>
<p>You can add additional fields to an object schema with the <code>.extend</code> method.</p>
<div><pre><span>const</span> <span>DogWithBreed</span> <span>=</span> <span>Dog</span><span>.</span><span>extend</span><span>(</span><span>{</span>
  <span>breed</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>You can use <code>.extend</code> to overwrite fields! Be careful with this power!</p>
<p></p><h3><code>.merge</code></h3><a href="#merge"></a><p></p>
<p>Equivalent to <code>A.extend(B.shape)</code>.</p>
<div><pre><span>const</span> <span>BaseTeacher</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>students</span>: <span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span> <span>}</span><span>)</span><span>;</span>
<span>const</span> <span>HasID</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>id</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>;</span>

<span>const</span> <span>Teacher</span> <span>=</span> <span>BaseTeacher</span><span>.</span><span>merge</span><span>(</span><span>HasID</span><span>)</span><span>;</span>
<span>type</span> <span>Teacher</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>Teacher</span><span>&gt;</span><span>;</span> <span>// =&gt; { students: string[], id: string }</span></pre></div>
<blockquote>
<p>If the two schemas share keys, the properties of B overrides the property of A. The returned schema also inherits the "unknownKeys" policy (strip/strict/passthrough) and the catchall schema of B.</p>
</blockquote>
<p></p><h3><code>.pick/.omit</code></h3><a href="#pickomit"></a><p></p>
<p>Inspired by TypeScript's built-in <code>Pick</code> and <code>Omit</code> utility types, all Zod object schemas have <code>.pick</code> and <code>.omit</code> methods that return a modified version. Consider this Recipe schema:</p>
<div><pre><span>const</span> <span>Recipe</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>id</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>ingredients</span>: <span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>To only keep certain keys, use <code>.pick</code> .</p>
<div><pre><span>const</span> <span>JustTheName</span> <span>=</span> <span>Recipe</span><span>.</span><span>pick</span><span>(</span><span>{</span> <span>name</span>: <span>true</span> <span>}</span><span>)</span><span>;</span>
<span>type</span> <span>JustTheName</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>JustTheName</span><span>&gt;</span><span>;</span>
<span>// =&gt; { name: string }</span></pre></div>
<p>To remove certain keys, use <code>.omit</code> .</p>
<div><pre><span>const</span> <span>NoIDRecipe</span> <span>=</span> <span>Recipe</span><span>.</span><span>omit</span><span>(</span><span>{</span> <span>id</span>: <span>true</span> <span>}</span><span>)</span><span>;</span>

<span>type</span> <span>NoIDRecipe</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>NoIDRecipe</span><span>&gt;</span><span>;</span>
<span>// =&gt; { name: string, ingredients: string[] }</span></pre></div>
<p></p><h3><code>.partial</code></h3><a href="#partial"></a><p></p>
<p>Inspired by the built-in TypeScript utility type <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype">Partial</a>, the <code>.partial</code> method makes all properties optional.</p>
<p>Starting from this object:</p>
<div><pre><span>const</span> <span>user</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>email</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>username</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// { email: string; username: string }</span></pre></div>
<p>We can create a partial version:</p>
<div><pre><span>const</span> <span>partialUser</span> <span>=</span> <span>user</span><span>.</span><span>partial</span><span>(</span><span>)</span><span>;</span>
<span>// { email?: string | undefined; username?: string | undefined }</span></pre></div>
<p>You can also specify which properties to make optional:</p>
<div><pre><span>const</span> <span>optionalEmail</span> <span>=</span> <span>user</span><span>.</span><span>partial</span><span>(</span><span>{</span>
  <span>email</span>: <span>true</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>/*</span>
<span>{</span>
<span>  email?: string | undefined;</span>
<span>  username: string</span>
<span>}</span>
<span>*/</span></pre></div>
<p></p><h3><code>.deepPartial</code></h3><a href="#deeppartial"></a><p></p>
<p>The <code>.partial</code> method is shallow — it only applies one level deep. There is also a "deep" version:</p>
<div><pre><span>const</span> <span>user</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>username</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>location</span>: <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
    <span>latitude</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
    <span>longitude</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span>
  <span>strings</span>: <span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>value</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>deepPartialUser</span> <span>=</span> <span>user</span><span>.</span><span>deepPartial</span><span>(</span><span>)</span><span>;</span>

<span>/*</span>
<span>{</span>
<span>  username?: string | undefined,</span>
<span>  location?: {</span>
<span>    latitude?: number | undefined;</span>
<span>    longitude?: number | undefined;</span>
<span>  } | undefined,</span>
<span>  strings?: { value?: string}[]</span>
<span>}</span>
<span>*/</span></pre></div>
<blockquote>
<p>Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.</p>
</blockquote>
<p></p><h3><code>.required</code></h3><a href="#required"></a><p></p>
<p>Contrary to the <code>.partial</code> method, the <code>.required</code> method makes all properties required.</p>
<p>Starting from this object:</p>
<div><pre><span>const</span> <span>user</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>email</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    <span>username</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>partial</span><span>(</span><span>)</span><span>;</span>
<span>// { email?: string | undefined; username?: string | undefined }</span></pre></div>
<p>We can create a required version:</p>
<div><pre><span>const</span> <span>requiredUser</span> <span>=</span> <span>user</span><span>.</span><span>required</span><span>(</span><span>)</span><span>;</span>
<span>// { email: string; username: string }</span></pre></div>
<p>You can also specify which properties to make required:</p>
<div><pre><span>const</span> <span>requiredEmail</span> <span>=</span> <span>user</span><span>.</span><span>required</span><span>(</span><span>{</span>
  <span>email</span>: <span>true</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>/*</span>
<span>{</span>
<span>  email: string;</span>
<span>  username?: string | undefined;</span>
<span>}</span>
<span>*/</span></pre></div>
<p></p><h3><code>.passthrough</code></h3><a href="#passthrough"></a><p></p>
<p>By default Zod object schemas strip out unrecognized keys during parsing.</p>
<div><pre><span>const</span> <span>person</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>person</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"bob dylan"</span><span>,</span>
  <span>extraKey</span>: <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; { name: "bob dylan" }</span>
<span>// extraKey has been stripped</span></pre></div>
<p>Instead, if you want to pass through unknown keys, use <code>.passthrough()</code> .</p>
<div><pre><span>person</span><span>.</span><span>passthrough</span><span>(</span><span>)</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"bob dylan"</span><span>,</span>
  <span>extraKey</span>: <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; { name: "bob dylan", extraKey: 61 }</span></pre></div>
<p></p><h3><code>.strict</code></h3><a href="#strict"></a><p></p>
<p>By default Zod object schemas strip out unrecognized keys during parsing. You can <em>disallow</em> unknown keys with <code>.strict()</code> . If there are any unknown keys in the input, Zod will throw an error.</p>
<div><pre><span>const</span> <span>person</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>strict</span><span>(</span><span>)</span><span>;</span>

<span>person</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"bob dylan"</span><span>,</span>
  <span>extraKey</span>: <span>61</span><span>,</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; throws ZodError</span></pre></div>
<p></p><h3><code>.strip</code></h3><a href="#strip"></a><p></p>
<p>You can use the <code>.strip</code> method to reset an object schema to the default behavior (stripping unrecognized keys).</p>
<p></p><h3><code>.catchall</code></h3><a href="#catchall"></a><p></p>
<p>You can pass a "catchall" schema into an object schema. All unknown keys will be validated against it.</p>
<div><pre><span>const</span> <span>person</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>catchall</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>person</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"bob dylan"</span><span>,</span>
  <span>validExtraKey</span>: <span>61</span><span>,</span> <span>// works fine</span>
<span>}</span><span>)</span><span>;</span>

<span>person</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"bob dylan"</span><span>,</span>
  <span>validExtraKey</span>: <span>false</span><span>,</span> <span>// fails</span>
<span>}</span><span>)</span><span>;</span>
<span>// =&gt; throws ZodError</span></pre></div>
<p>Using <code>.catchall()</code> obviates <code>.passthrough()</code> , <code>.strip()</code> , or <code>.strict()</code>. All keys are now considered "known".</p>
<p></p><h2>Arrays</h2><a href="#arrays"></a><p></p>
<div><pre><span>const</span> <span>stringArray</span> <span>=</span> <span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// equivalent</span>
<span>const</span> <span>stringArray</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span></pre></div>
<p>Be careful with the <code>.array()</code> method. It returns a new <code>ZodArray</code> instance. This means the <em>order</em> in which you call methods matters. For instance:</p>
<div><pre><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span> <span>// (string | undefined)[]</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span> <span>// string[] | undefined</span></pre></div>
<p></p><h3><code>.element</code></h3><a href="#element"></a><p></p>
<p>Use <code>.element</code> to access the schema for an element of the array.</p>
<div><pre><span>stringArray</span><span>.</span><span>element</span><span>;</span> <span>// =&gt; string schema</span></pre></div>
<p></p><h3><code>.nonempty</code></h3><a href="#nonempty"></a><p></p>
<p>If you want to ensure that an array contains at least one element, use <code>.nonempty()</code>.</p>
<div><pre><span>const</span> <span>nonEmptyStrings</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>)</span><span>;</span>
<span>// the inferred type is now</span>
<span>// [string, ...string[]]</span>

<span>nonEmptyStrings</span><span>.</span><span>parse</span><span>(</span><span>[</span><span>]</span><span>)</span><span>;</span> <span>// throws: "Array cannot be empty"</span>
<span>nonEmptyStrings</span><span>.</span><span>parse</span><span>(</span><span>[</span><span>"Ariana Grande"</span><span>]</span><span>)</span><span>;</span> <span>// passes</span></pre></div>
<p>You can optionally specify a custom error message:</p>
<div><pre><span>// optional custom error message</span>
<span>const</span> <span>nonEmptyStrings</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>{</span>
  <span>message</span>: <span>"Can't be empty!"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.min/.max/.length</code></h3><a href="#minmaxlength"></a><p></p>
<div><pre><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or more items</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or fewer items</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>.</span><span>length</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 items exactly</span></pre></div>
<p>Unlike <code>.nonempty()</code> these methods do not change the inferred type.</p>
<p></p><h2>Tuples</h2><a href="#tuples"></a><p></p>
<p>Unlike arrays, tuples have a fixed number of elements and each element can have a different type.</p>
<div><pre><span>const</span> <span>athleteSchema</span> <span>=</span> <span>z</span><span>.</span><span>tuple</span><span>(</span><span>[</span>
  <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>// name</span>
  <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>// jersey number</span>
  <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
    <span>pointsScored</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span> <span>// statistics</span>
<span>]</span><span>)</span><span>;</span>

<span>type</span> <span>Athlete</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>athleteSchema</span><span>&gt;</span><span>;</span>
<span>// type Athlete = [string, number, { pointsScored: number }]</span></pre></div>
<p>A variadic ("rest") argument can be added with the <code>.rest</code> method.</p>
<div><pre><span>const</span> <span>variadicTuple</span> <span>=</span> <span>z</span><span>.</span><span>tuple</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>]</span><span>)</span><span>.</span><span>rest</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>const</span> <span>result</span> <span>=</span> <span>variadicTuple</span><span>.</span><span>parse</span><span>(</span><span>[</span><span>"hello"</span><span>,</span> <span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>]</span><span>)</span><span>;</span>
<span>// =&gt; [string, ...number[]];</span></pre></div>
<p></p><h2>Unions</h2><a href="#unions"></a><p></p>
<p>Zod includes a built-in <code>z.union</code> method for composing "OR" types.</p>
<div><pre><span>const</span> <span>stringOrNumber</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>

<span>stringOrNumber</span><span>.</span><span>parse</span><span>(</span><span>"foo"</span><span>)</span><span>;</span> <span>// passes</span>
<span>stringOrNumber</span><span>.</span><span>parse</span><span>(</span><span>14</span><span>)</span><span>;</span> <span>// passes</span></pre></div>
<p>Zod will test the input against each of the "options" in order and return the first value that validates successfully.</p>
<p>For convenience, you can also use the <a href="#or"><code>.or</code> method</a>:</p>
<div><pre><span>const</span> <span>stringOrNumber</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p><strong>Optional string validation:</strong></p>
<p>To validate an optional form input, you can union the desired string validation with an empty string <a href="#literals">literal</a>.</p>
<p>This example validates an input that is optional but needs to contain a <a href="#strings">valid URL</a>:</p>
<div><pre><span>const</span> <span>optionalUrl</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>url</span><span>(</span><span>)</span><span>.</span><span>nullish</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>literal</span><span>(</span><span>""</span><span>)</span><span>]</span><span>)</span><span>;</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>optionalUrl</span><span>.</span><span>safeParse</span><span>(</span><span>undefined</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>optionalUrl</span><span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>optionalUrl</span><span>.</span><span>safeParse</span><span>(</span><span>""</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>optionalUrl</span><span>.</span><span>safeParse</span><span>(</span><span>"https://zod.dev"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>optionalUrl</span><span>.</span><span>safeParse</span><span>(</span><span>"not a valid url"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// false</span></pre></div>
<p></p><h2>Discriminated unions</h2><a href="#discriminated-unions"></a><p></p>
<p>A discriminated union is a union of object schemas that all share a particular key.</p>
<div><pre><span>type</span> <span>MyUnion</span> <span>=</span>
  <span>|</span> <span>{</span> <span>status</span>: <span>"success"</span><span>;</span> <span>data</span>: <span>string</span> <span>}</span>
  <span>|</span> <span>{</span> <span>status</span>: <span>"failed"</span><span>;</span> <span>error</span>: <span>Error</span> <span>}</span><span>;</span></pre></div>
<p>Such unions can be represented with the <code>z.discriminatedUnion</code> method. This enables faster evaluation, because Zod can check the <em>discriminator key</em> (<code>status</code> in the example above) to determine which schema should be used to parse the input. This makes parsing more efficient and lets Zod report friendlier errors.</p>
<p>With the basic union method, the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".</p>
<div><pre><span>const</span> <span>myUnion</span> <span>=</span> <span>z</span><span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>status</span>: <span>z</span><span>.</span><span>literal</span><span>(</span><span>"success"</span><span>)</span><span>,</span> <span>data</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>,</span>
  <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>status</span>: <span>z</span><span>.</span><span>literal</span><span>(</span><span>"failed"</span><span>)</span><span>,</span> <span>error</span>: <span>z</span><span>.</span><span>instanceof</span><span>(</span><span>Error</span><span>)</span> <span>}</span><span>)</span><span>,</span>
<span>]</span><span>)</span><span>;</span>

<span>myUnion</span><span>.</span><span>parse</span><span>(</span><span>{</span> <span>status</span>: <span>"success"</span><span>,</span> <span>data</span>: <span>"yippie ki yay"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p>You can extract a reference to the array of schemas with the <code>.options</code> property.</p>
<div><pre><span>myUnion</span><span>.</span><span>options</span><span>;</span> <span>// [ZodObject&lt;...&gt;, ZodObject&lt;...&gt;]</span></pre></div>
<p>To merge two or more discriminated unions, use <code>.options</code> with destructuring.</p>
<div><pre><span>const</span> <span>A</span> <span>=</span> <span>z</span><span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  <span>/* options */</span>
<span>]</span><span>)</span><span>;</span>
<span>const</span> <span>B</span> <span>=</span> <span>z</span><span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>
  <span>/* options */</span>
<span>]</span><span>)</span><span>;</span>

<span>const</span> <span>AB</span> <span>=</span> <span>z</span><span>.</span><span>discriminatedUnion</span><span>(</span><span>"status"</span><span>,</span> <span>[</span>...<span>A</span><span>.</span><span>options</span><span>,</span> ...<span>B</span><span>.</span><span>options</span><span>]</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Records</h2><a href="#records"></a><p></p>
<p>Record schemas are used to validate types such as <code>Record&lt;string, number&gt;</code>. This is particularly useful for storing or caching items by ID.</p>

<div><pre><span>const</span> <span>User</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>;</span>

<span>const</span> <span>UserStore</span> <span>=</span> <span>z</span><span>.</span><span>record</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>User</span><span>)</span><span>;</span>
<span>type</span> <span>UserStore</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>UserStore</span><span>&gt;</span><span>;</span>
<span>// =&gt; Record&lt;string, { name: string }&gt;</span></pre></div>
<p>The schema and inferred type can be used like so:</p>
<div><pre><span>const</span> <span>userStore</span>: <span>UserStore</span> <span>=</span> <span>{</span><span>}</span><span>;</span>

<span>userStore</span><span>[</span><span>"77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"</span><span>]</span> <span>=</span> <span>{</span>
  <span>name</span>: <span>"Carlotta"</span><span>,</span>
<span>}</span><span>;</span> <span>// passes</span>

<span>userStore</span><span>[</span><span>"77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"</span><span>]</span> <span>=</span> <span>{</span>
  <span>whatever</span>: <span>"Ice cream sundae"</span><span>,</span>
<span>}</span><span>;</span> <span>// TypeError</span></pre></div>
<p><strong>A note on numerical keys</strong></p>
<p>While <code>z.record(keyType, valueType)</code> is able to accept numerical key types and TypeScript's built-in Record type is <code>Record&lt;KeyType, ValueType&gt;</code>, it's hard to represent the TypeScript type <code>Record&lt;number, any&gt;</code> in Zod.</p>
<p>As it turns out, TypeScript's behavior surrounding <code>[k: number]</code> is a little unintuitive:</p>
<div><pre><span>const</span> <span>testMap</span>: <span>{</span> <span>[</span><span>k</span>: <span>number</span><span>]</span>: <span>string</span> <span>}</span> <span>=</span> <span>{</span>
  <span>1</span>: <span>"one"</span><span>,</span>
<span>}</span><span>;</span>

<span>for</span> <span>(</span><span>const</span> <span>key</span> <span>in</span> <span>testMap</span><span>)</span> <span>{</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>`<span><span>${</span><span>key</span><span>}</span></span>: <span><span>${</span><span>typeof</span> <span>key</span><span>}</span></span>`</span><span>)</span><span>;</span>
<span>}</span>
<span>// prints: `1: string`</span></pre></div>
<p>As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.</p>
<p></p><h2>Maps</h2><a href="#maps"></a><p></p>
<div><pre><span>const</span> <span>stringNumberMap</span> <span>=</span> <span>z</span><span>.</span><span>map</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>type</span> <span>StringNumberMap</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>stringNumberMap</span><span>&gt;</span><span>;</span>
<span>// type StringNumberMap = Map&lt;string, number&gt;</span></pre></div>
<p></p><h2>Sets</h2><a href="#sets"></a><p></p>
<div><pre><span>const</span> <span>numberSet</span> <span>=</span> <span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>type</span> <span>NumberSet</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>numberSet</span><span>&gt;</span><span>;</span>
<span>// type NumberSet = Set&lt;number&gt;</span></pre></div>
<p>Set schemas can be further constrained with the following utility methods.</p>
<div><pre><span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>nonempty</span><span>(</span><span>)</span><span>;</span> <span>// must contain at least one item</span>
<span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or more items</span>
<span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>max</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 or fewer items</span>
<span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>size</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// must contain 5 items exactly</span></pre></div>
<p></p><h2>Intersections</h2><a href="#intersections"></a><p></p>
<p>Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.</p>
<div><pre><span>const</span> <span>Person</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>Employee</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>role</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>EmployedPerson</span> <span>=</span> <span>z</span><span>.</span><span>intersection</span><span>(</span><span>Person</span><span>,</span> <span>Employee</span><span>)</span><span>;</span>

<span>// equivalent to:</span>
<span>const</span> <span>EmployedPerson</span> <span>=</span> <span>Person</span><span>.</span><span>and</span><span>(</span><span>Employee</span><span>)</span><span>;</span></pre></div>
<p>Though in many cases, it is recommended to use <code>A.merge(B)</code> to merge two objects. The <code>.merge</code> method returns a new <code>ZodObject</code> instance, whereas <code>A.and(B)</code> returns a less useful <code>ZodIntersection</code> instance that lacks common object methods like <code>pick</code> and <code>omit</code>.</p>
<div><pre><span>const</span> <span>a</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>b</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>c</span> <span>=</span> <span>z</span><span>.</span><span>intersection</span><span>(</span><span>a</span><span>,</span> <span>b</span><span>)</span><span>;</span>

<span>type</span> <span>c</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>c</span><span>&gt;</span><span>;</span> <span>// =&gt; number</span></pre></div>


<p></p><h2>Recursive types</h2><a href="#recursive-types"></a><p></p>
<p>You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".</p>
<div><pre><span>const</span> <span>baseCategorySchema</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>Category</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>baseCategorySchema</span><span>&gt;</span> <span>&amp;</span> <span>{</span>
  <span>subcategories</span>: <span>Category</span><span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>const</span> <span>categorySchema</span>: <span>z</span><span>.</span><span>ZodType</span><span>&lt;</span><span>Category</span><span>&gt;</span> <span>=</span> <span>baseCategorySchema</span><span>.</span><span>extend</span><span>(</span><span>{</span>
  <span>subcategories</span>: <span>z</span><span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>categorySchema</span><span>.</span><span>array</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>categorySchema</span><span>.</span><span>parse</span><span>(</span><span>{</span>
  <span>name</span>: <span>"People"</span><span>,</span>
  <span>subcategories</span>: <span>[</span>
    <span>{</span>
      <span>name</span>: <span>"Politicians"</span><span>,</span>
      <span>subcategories</span>: <span>[</span>
        <span>{</span>
          <span>name</span>: <span>"Presidents"</span><span>,</span>
          <span>subcategories</span>: <span>[</span><span>]</span><span>,</span>
        <span>}</span><span>,</span>
      <span>]</span><span>,</span>
    <span>}</span><span>,</span>
  <span>]</span><span>,</span>
<span>}</span><span>)</span><span>;</span> <span>// passes</span></pre></div>
<p>Thanks to <a href="https://github.com/crasite">crasite</a> for this example.</p>
<p></p><h3>ZodType with ZodEffects</h3><a href="#zodtype-with-zodeffects"></a><p></p>
<p>When using <code>z.ZodType</code> with <code>z.ZodEffects</code> (
<a href="https://github.com/colinhacks/zod#refine"><code>.refine</code></a>,
<a href="https://github.com/colinhacks/zod#transform"><code>.transform</code></a>,
<a href="https://github.com/colinhacks/zod#preprocess"><code>preprocess</code></a>,
etc...
), you will need to define the input and output types of the schema. <code>z.ZodType&lt;Output, z.ZodTypeDef, Input&gt;</code></p>
<div><pre><span>const</span> <span>isValidId</span> <span>=</span> <span>(</span><span>id</span>: <span>string</span><span>)</span>: <span>id</span> is `${<span>string</span><span>}</span>/${<span>string</span><span>}</span>` <span>=&gt;</span>
  <span>id</span><span>.</span><span>split</span><span>(</span><span>"/"</span><span>)</span><span>.</span><span>length</span> <span>===</span> <span>2</span><span>;</span>

<span>const</span> <span>baseSchema</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>id</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>isValidId</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>Input</span> <span>=</span> <span>z</span><span>.</span><span>input</span><span>&lt;</span><span>typeof</span> <span>baseSchema</span><span>&gt;</span> <span>&amp;</span> <span>{</span>
  <span>children</span>: <span>Input</span><span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>type</span> <span>Output</span> <span>=</span> <span>z</span><span>.</span><span>output</span><span>&lt;</span><span>typeof</span> <span>baseSchema</span><span>&gt;</span> <span>&amp;</span> <span>{</span>
  <span>children</span>: <span>Output</span><span>[</span><span>]</span><span>;</span>
<span>}</span><span>;</span>

<span>const</span> <span>schema</span>: <span>z</span><span>.</span><span>ZodType</span><span>&lt;</span><span>Output</span><span>,</span> <span>z</span><span>.</span><span>ZodTypeDef</span><span>,</span> <span>Input</span><span>&gt;</span> <span>=</span> <span>baseSchema</span><span>.</span><span>extend</span><span>(</span><span>{</span>
  <span>children</span>: <span>z</span><span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>schema</span><span>.</span><span>array</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>Thanks to <a href="https://github.com/marcus13371337">marcus13371337</a> and <a href="https://github.com/JoelBeeldi">JoelBeeldi</a> for this example.</p>
<p></p><h3>JSON type</h3><a href="#json-type"></a><p></p>
<p>If you want to validate any JSON value, you can use the snippet below.</p>
<div><pre><span>const</span> <span>literalSchema</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>null</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>type</span> <span>Literal</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>literalSchema</span><span>&gt;</span><span>;</span>
<span>type</span> <span>Json</span> <span>=</span> <span>Literal</span> <span>|</span> <span>{</span> <span>[</span><span>key</span>: <span>string</span><span>]</span>: <span>Json</span> <span>}</span> <span>|</span> <span>Json</span><span>[</span><span>]</span><span>;</span>
<span>const</span> <span>jsonSchema</span>: <span>z</span><span>.</span><span>ZodType</span><span>&lt;</span><span>Json</span><span>&gt;</span> <span>=</span> <span>z</span><span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span>
  <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>literalSchema</span><span>,</span> <span>z</span><span>.</span><span>array</span><span>(</span><span>jsonSchema</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>record</span><span>(</span><span>jsonSchema</span><span>)</span><span>]</span><span>)</span>
<span>)</span><span>;</span>

<span>jsonSchema</span><span>.</span><span>parse</span><span>(</span><span>data</span><span>)</span><span>;</span></pre></div>
<p>Thanks to <a href="https://github.com/ggoodman">ggoodman</a> for suggesting this.</p>
<p></p><h3>Cyclical objects</h3><a href="#cyclical-objects"></a><p></p>
<p>Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop in some cases.</p>
<blockquote>
<p>To detect cyclical objects before they cause problems, consider <a href="https://gist.github.com/colinhacks/d35825e505e635df27cc950776c5500b">this approach</a>.</p>
</blockquote>
<p></p><h2>Promises</h2><a href="#promises"></a><p></p>
<div><pre><span>const</span> <span>numberPromise</span> <span>=</span> <span>z</span><span>.</span><span>promise</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p>"Parsing" works a little differently with promise schemas. Validation happens in two parts:</p>
<ol>
<li>Zod synchronously checks that the input is an instance of Promise (i.e. an object with <code>.then</code> and <code>.catch</code> methods.).</li>
<li>Zod uses <code>.then</code> to attach an additional validation step onto the existing Promise. You'll have to use <code>.catch</code> on the returned Promise to handle validation failures.</li>
</ol>
<div><pre><span>numberPromise</span><span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>
<span>// ZodError: Non-Promise type: string</span>

<span>numberPromise</span><span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>"tuna"</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; Promise&lt;number&gt;</span>

<span>const</span> <span>test</span> <span>=</span> <span>async</span> <span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>await</span> <span>numberPromise</span><span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>"tuna"</span><span>)</span><span>)</span><span>;</span>
  <span>// ZodError: Non-number type: string</span>

  <span>await</span> <span>numberPromise</span><span>.</span><span>parse</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3.14</span><span>)</span><span>)</span><span>;</span>
  <span>// =&gt; 3.14</span>
<span>}</span><span>;</span></pre></div>

<p></p><h2>Instanceof</h2><a href="#instanceof"></a><p></p>
<p>You can use <code>z.instanceof</code> to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.</p>
<div><pre><span>class</span> <span>Test</span> <span>{</span>
  <span>name</span>: <span>string</span><span>;</span>
<span>}</span>

<span>const</span> <span>TestSchema</span> <span>=</span> <span>z</span><span>.</span><span>instanceof</span><span>(</span><span>Test</span><span>)</span><span>;</span>

<span>const</span> <span>blob</span>: <span>any</span> <span>=</span> <span>"whatever"</span><span>;</span>
<span>TestSchema</span><span>.</span><span>parse</span><span>(</span><span>new</span> <span>Test</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// passes</span>
<span>TestSchema</span><span>.</span><span>parse</span><span>(</span><span>blob</span><span>)</span><span>;</span> <span>// throws</span></pre></div>
<p></p><h2>Functions</h2><a href="#functions"></a><p></p>
<p>Zod also lets you define "function schemas". This makes it easy to validate the inputs and outputs of a function without intermixing your validation code and "business logic".</p>
<p>You can create a function schema with <code>z.function(args, returnType)</code> .</p>
<div><pre><span>const</span> <span>myFunction</span> <span>=</span> <span>z</span><span>.</span><span>function</span><span>(</span><span>)</span><span>;</span>

<span>type</span> <span>myFunction</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>myFunction</span><span>&gt;</span><span>;</span>
<span>// =&gt; ()=&gt;unknown</span></pre></div>
<p>Define inputs and outputs.</p>
<div><pre><span>const</span> <span>myFunction</span> <span>=</span> <span>z</span>
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span> <span>// accepts an arbitrary number of arguments</span>
  <span>.</span><span>returns</span><span>(</span><span>z</span><span>.</span><span>boolean</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>type</span> <span>myFunction</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>myFunction</span><span>&gt;</span><span>;</span>
<span>// =&gt; (arg0: string, arg1: number)=&gt;boolean</span></pre></div>

<p>Function schemas have an <code>.implement()</code> method which accepts a function and returns a new function that automatically validates its inputs and outputs.</p>
<div><pre><span>const</span> <span>trimmedLength</span> <span>=</span> <span>z</span>
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span> <span>// accepts an arbitrary number of arguments</span>
  <span>.</span><span>returns</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>implement</span><span>(</span><span>(</span><span>x</span><span>)</span> <span>=&gt;</span> <span>{</span>
    <span>// TypeScript knows x is a string!</span>
    <span>return</span> <span>x</span><span>.</span><span>trim</span><span>(</span><span>)</span><span>.</span><span>length</span><span>;</span>
  <span>}</span><span>)</span><span>;</span>

<span>trimmedLength</span><span>(</span><span>"sandwich"</span><span>)</span><span>;</span> <span>// =&gt; 8</span>
<span>trimmedLength</span><span>(</span><span>" asdf "</span><span>)</span><span>;</span> <span>// =&gt; 4</span></pre></div>
<p>If you only care about validating inputs, just don't call the <code>.returns()</code> method. The output type will be inferred from the implementation.</p>
<blockquote>
<p>You can use the special <code>z.void()</code> option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)</p>
</blockquote>
<div><pre><span>const</span> <span>myFunction</span> <span>=</span> <span>z</span>
  <span>.</span><span>function</span><span>(</span><span>)</span>
  <span>.</span><span>args</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>implement</span><span>(</span><span>(</span><span>arg</span><span>)</span> <span>=&gt;</span> <span>{</span>
    <span>return</span> <span>[</span><span>arg</span><span>.</span><span>length</span><span>]</span><span>;</span>
  <span>}</span><span>)</span><span>;</span>

<span>myFunction</span><span>;</span> <span>// (arg: string)=&gt;number[]</span></pre></div>
<p>Extract the input and output schemas from a function schema.</p>
<div><pre><span>myFunction</span><span>.</span><span>parameters</span><span>(</span><span>)</span><span>;</span>
<span>// =&gt; ZodTuple&lt;[ZodString, ZodNumber]&gt;</span>

<span>myFunction</span><span>.</span><span>returnType</span><span>(</span><span>)</span><span>;</span>
<span>// =&gt; ZodBoolean</span></pre></div>

<p></p><h2>Preprocess</h2><a href="#preprocess"></a><p></p>
<blockquote>
<p>Zod now supports primitive coercion without the need for <code>.preprocess()</code>. See the <a href="#coercion-for-primitives">coercion docs</a> for more information.</p>
</blockquote>
<p>Typically Zod operates under a "parse then transform" paradigm. Zod validates the input first, then passes it through a chain of transformation functions. (For more information about transforms, read the <a href="#transform">.transform docs</a>.)</p>
<p>But sometimes you want to apply some transform to the input <em>before</em> parsing happens. A common use case: type coercion. Zod enables this with the <code>z.preprocess()</code>.</p>
<div><pre><span>const</span> <span>castToString</span> <span>=</span> <span>z</span><span>.</span><span>preprocess</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>String</span><span>(</span><span>val</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p>This returns a <code>ZodEffects</code> instance. <code>ZodEffects</code> is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.</p>
<p></p><h2>Custom schemas</h2><a href="#custom-schemas"></a><p></p>
<p>You can create a Zod schema for any TypeScript type by using <code>z.custom()</code>. This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.</p>
<div><pre><span>const</span> <span>px</span> <span>=</span> <span>z</span><span>.</span><span>custom</span><span>&lt;</span>`${<span>number</span><span>}</span>px`<span>&gt;</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>return</span> <span>typeof</span> <span>val</span> <span>===</span> <span>"string"</span> ? <span><span>/</span>^\d+px$<span>/</span></span><span>.</span><span>test</span><span>(</span><span>val</span><span>)</span> : <span>false</span><span>;</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>px</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>px</span><span>&gt;</span><span>;</span> <span>// `${number}px`</span>

<span>px</span><span>.</span><span>parse</span><span>(</span><span>"42px"</span><span>)</span><span>;</span> <span>// "42px"</span>
<span>px</span><span>.</span><span>parse</span><span>(</span><span>"42vw"</span><span>)</span><span>;</span> <span>// throws;</span></pre></div>
<p>If you don't provide a validation function, Zod will allow any value. This can be dangerous!</p>
<div><pre><span>z</span><span>.</span><span>custom</span><span>&lt;</span><span>{</span> <span>arg</span>: <span>string</span> <span>}</span><span>&gt;</span><span>(</span><span>)</span><span>;</span> <span>// performs no validation</span></pre></div>
<p>You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of <a href="#refine"><code>.refine</code></a>.</p>
<div><pre><span>z</span><span>.</span><span>custom</span><span>&lt;</span>...<span>&gt;</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> ...<span>,</span> <span>"custom error message"</span><span>)</span><span>;</span></pre></div>
<p></p><h2>Schema methods</h2><a href="#schema-methods"></a><p></p>
<p>All Zod schemas contain certain methods.</p>
<p></p><h3><code>.parse</code></h3><a href="#parse"></a><p></p>
<p><code>.parse(data: unknown): T</code></p>
<p>Given any Zod schema, you can call its <code>.parse</code> method to check <code>data</code> is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.</p>
<blockquote>
<p>IMPORTANT: The value returned by <code>.parse</code> is a <em>deep clone</em> of the variable you passed in.</p>
</blockquote>
<div><pre><span>const</span> <span>stringSchema</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>

<span>stringSchema</span><span>.</span><span>parse</span><span>(</span><span>"fish"</span><span>)</span><span>;</span> <span>// =&gt; returns "fish"</span>
<span>stringSchema</span><span>.</span><span>parse</span><span>(</span><span>12</span><span>)</span><span>;</span> <span>// throws error</span></pre></div>
<p></p><h3><code>.parseAsync</code></h3><a href="#parseasync"></a><p></p>
<p><code>.parseAsync(data:unknown): Promise&lt;T&gt;</code></p>
<p>If you use asynchronous <a href="#refine">refinements</a> or <a href="#transform">transforms</a> (more on those later), you'll need to use <code>.parseAsync</code>.</p>
<div><pre><span>const</span> <span>stringSchema</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>async</span> <span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span> <span>&lt;=</span> <span>8</span><span>)</span><span>;</span>

<span>await</span> <span>stringSchema</span><span>.</span><span>parseAsync</span><span>(</span><span>"hello"</span><span>)</span><span>;</span> <span>// =&gt; returns "hello"</span>
<span>await</span> <span>stringSchema</span><span>.</span><span>parseAsync</span><span>(</span><span>"hello world"</span><span>)</span><span>;</span> <span>// =&gt; throws error</span></pre></div>
<p></p><h3><code>.safeParse</code></h3><a href="#safeparse"></a><p></p>
<p><code>.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }</code></p>
<p>If you don't want Zod to throw errors when validation fails, use <code>.safeParse</code>. This method returns an object containing either the successfully parsed data or a ZodError instance containing detailed information about the validation problems.</p>
<div><pre><span>stringSchema</span><span>.</span><span>safeParse</span><span>(</span><span>12</span><span>)</span><span>;</span>
<span>// =&gt; { success: false; error: ZodError }</span>

<span>stringSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"billie"</span><span>)</span><span>;</span>
<span>// =&gt; { success: true; data: 'billie' }</span></pre></div>
<p>The result is a <em>discriminated union</em>, so you can handle errors very conveniently:</p>
<div><pre><span>const</span> <span>result</span> <span>=</span> <span>stringSchema</span><span>.</span><span>safeParse</span><span>(</span><span>"billie"</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>!</span><span>result</span><span>.</span><span>success</span><span>)</span> <span>{</span>
  <span>// handle error then return</span>
  <span>result</span><span>.</span><span>error</span><span>;</span>
<span>}</span> <span>else</span> <span>{</span>
  <span>// do something</span>
  <span>result</span><span>.</span><span>data</span><span>;</span>
<span>}</span></pre></div>
<p></p><h3><code>.safeParseAsync</code></h3><a href="#safeparseasync"></a><p></p>
<blockquote>
<p>Alias: <code>.spa</code></p>
</blockquote>
<p>An asynchronous version of <code>safeParse</code>.</p>
<div><pre><span>await</span> <span>stringSchema</span><span>.</span><span>safeParseAsync</span><span>(</span><span>"billie"</span><span>)</span><span>;</span></pre></div>
<p>For convenience, this has been aliased to <code>.spa</code>:</p>
<div><pre><span>await</span> <span>stringSchema</span><span>.</span><span>spa</span><span>(</span><span>"billie"</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.refine</code></h3><a href="#refine"></a><p></p>
<p><code>.refine(validator: (data:T)=&gt;any, params?: RefineParams)</code></p>
<p>Zod lets you provide custom validation logic via <em>refinements</em>. (For advanced features like creating multiple issues and customizing error codes, see <a href="#superrefine"><code>.superRefine</code></a>.)</p>
<p>Zod was designed to mirror TypeScript as closely as possible. But there are many so-called "refinement types" you may wish to check for that can't be represented in TypeScript's type system. For instance: checking that a number is an integer or that a string is a valid email address.</p>
<p>For example, you can define a custom validation check on <em>any</em> Zod schema with <code>.refine</code> :</p>
<div><pre><span>const</span> <span>myString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span> <span>&lt;=</span> <span>255</span><span>,</span> <span>{</span>
  <span>message</span>: <span>"String can't be more than 255 characters"</span><span>,</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<blockquote>
<p> Refinement functions should not throw. Instead they should return a falsy value to signal failure.</p>
</blockquote>
<p></p><h4>Arguments</h4><a href="#arguments"></a><p></p>
<p>As you can see, <code>.refine</code> takes two arguments.</p>
<ol>
<li>The first is the validation function. This function takes one input (of type <code>T</code> — the inferred type of the schema) and returns <code>any</code>. Any truthy value will pass validation. (Prior to zod@1.6.2 the validation function had to return a boolean.)</li>
<li>The second argument accepts some options. You can use this to customize certain error-handling behavior:</li>
</ol>
<div><pre><span>type</span> <span>RefineParams</span> <span>=</span> <span>{</span>
  <span>// override error message</span>
  <span>message</span>?: <span>string</span><span>;</span>

  <span>// appended to error path</span>
  <span>path</span>?: <span>(</span><span>string</span> <span>|</span> <span>number</span><span>)</span><span>[</span><span>]</span><span>;</span>

  <span>// params object you can use to customize message</span>
  <span>// in error map</span>
  <span>params</span>?: <span>object</span><span>;</span>
<span>}</span><span>;</span></pre></div>
<p>For advanced cases, the second argument can also be a function that returns <code>RefineParams</code>.</p>
<div><pre><span>const</span> <span>longString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span>
  <span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span> <span>&gt;</span> <span>10</span><span>,</span>
  <span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>(</span><span>{</span> <span>message</span>: <span>`<span><span>${</span><span>val</span><span>}</span></span> is not more than 10 characters`</span> <span>}</span><span>)</span>
<span>)</span><span>;</span></pre></div>
<p></p><h4>Customize error path</h4><a href="#customize-error-path"></a><p></p>
<div><pre><span>const</span> <span>passwordForm</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>password</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    <span>confirm</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span><span>data</span><span>)</span> <span>=&gt;</span> <span>data</span><span>.</span><span>password</span> <span>===</span> <span>data</span><span>.</span><span>confirm</span><span>,</span> <span>{</span>
    <span>message</span>: <span>"Passwords don't match"</span><span>,</span>
    <span>path</span>: <span>[</span><span>"confirm"</span><span>]</span><span>,</span> <span>// path of error</span>
  <span>}</span><span>)</span><span>;</span>

<span>passwordForm</span><span>.</span><span>parse</span><span>(</span><span>{</span> <span>password</span>: <span>"asdf"</span><span>,</span> <span>confirm</span>: <span>"qwer"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p>Because you provided a <code>path</code> parameter, the resulting error will be:</p>
<div><pre><span>ZodError</span> <span>{</span>
  <span>issues</span>: <span>[</span><span>{</span>
    <span>"code"</span>: <span>"custom"</span><span>,</span>
    <span>"path"</span>: <span>[</span> <span>"confirm"</span> <span>]</span><span>,</span>
    <span>"message"</span>: <span>"Passwords don't match"</span>
  <span>}</span><span>]</span>
<span>}</span></pre></div>
<p></p><h4>Asynchronous refinements</h4><a href="#asynchronous-refinements"></a><p></p>
<p>Refinements can also be async:</p>
<div><pre><span>const</span> <span>userId</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>refine</span><span>(</span><span>async</span> <span>(</span><span>id</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>// verify that ID exists in database</span>
  <span>return</span> <span>true</span><span>;</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<blockquote>
<p> If you use async refinements, you must use the <code>.parseAsync</code> method to parse data! Otherwise Zod will throw an error.</p>
</blockquote>
<p></p><h4>Relationship to transforms</h4><a href="#relationship-to-transforms"></a><p></p>
<p>Transforms and refinements can be interleaved:</p>
<div><pre><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span> <span>&gt;</span> <span>25</span><span>)</span><span>;</span></pre></div>

<p></p><h3><code>.superRefine</code></h3><a href="#superrefine"></a><p></p>
<p>The <code>.refine</code> method is actually syntactic sugar atop a more versatile (and verbose) method called <code>superRefine</code>. Here's an example:</p>
<div><pre><span>const</span> <span>Strings</span> <span>=</span> <span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>superRefine</span><span>(</span><span>(</span><span>val</span><span>,</span> <span>ctx</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>if</span> <span>(</span><span>val</span><span>.</span><span>length</span> <span>&gt;</span> <span>3</span><span>)</span> <span>{</span>
    <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
      <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>too_big</span><span>,</span>
      <span>maximum</span>: <span>3</span><span>,</span>
      <span>type</span>: <span>"array"</span><span>,</span>
      <span>inclusive</span>: <span>true</span><span>,</span>
      <span>message</span>: <span>"Too many items 😡"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>

  <span>if</span> <span>(</span><span>val</span><span>.</span><span>length</span> <span>!==</span> <span>new</span> <span>Set</span><span>(</span><span>val</span><span>)</span><span>.</span><span>size</span><span>)</span> <span>{</span>
    <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
      <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>custom</span><span>,</span>
      <span>message</span>: <span>`No duplicates allowed.`</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p>You can add as many issues as you like. If <code>ctx.addIssue</code> is <em>not</em> called during the execution of the function, validation passes.</p>
<p>Normally refinements always create issues with a <code>ZodIssueCode.custom</code> error code, but with <code>superRefine</code> it's possible to throw issues of any <code>ZodIssueCode</code>. Each issue code is described in detail in the Error Handling guide: <a href="https://github.com/colinhacks/zod/blob/main/ERROR_HANDLING.md">ERROR_HANDLING.md</a>.</p>
<p></p><h4>Abort early</h4><a href="#abort-early"></a><p></p>
<p>By default, parsing will continue even after a refinement check fails. For instance, if you chain together multiple refinements, they will all be executed. However, it may be desirable to <em>abort early</em> to prevent later refinements from being executed. To achieve this, pass the <code>fatal</code> flag to <code>ctx.addIssue</code> and return <code>z.NEVER</code>.</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>superRefine</span><span>(</span><span>(</span><span>val</span><span>,</span> <span>ctx</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>if</span> <span>(</span><span>val</span> <span>&lt;</span> <span>10</span><span>)</span> <span>{</span>
    <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
      <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>custom</span><span>,</span>
      <span>message</span>: <span>"should be &gt;= 10"</span><span>,</span>
      <span>fatal</span>: <span>true</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>

    <span>return</span> <span>z</span><span>.</span><span>NEVER</span><span>;</span>
  <span>}</span>

  <span>if</span> <span>(</span><span>val</span> <span>!==</span> <span>12</span><span>)</span> <span>{</span>
    <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
      <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>custom</span><span>,</span>
      <span>message</span>: <span>"should be twelve"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>
  <span>}</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h4>Type refinements</h4><a href="#type-refinements"></a><p></p>
<p>If you provide a <a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates">type predicate</a> to <code>.refine()</code> or <code>.superRefine()</code>, the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>first</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    <span>second</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>nullable</span><span>(</span><span>)</span>
  <span>.</span><span>superRefine</span><span>(</span><span>(</span><span>arg</span><span>,</span> <span>ctx</span><span>)</span>: <span>arg</span> is <span>{</span> <span>first</span>: <span>string</span><span>;</span> <span>second</span>: <span>number</span> <span>}</span> <span>=&gt;</span> <span>{</span>
    <span>if</span> <span>(</span><span>!</span><span>arg</span><span>)</span> <span>{</span>
      <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
        <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>custom</span><span>,</span> <span>// customize your issue</span>
        <span>message</span>: <span>"object should exist"</span><span>,</span>
      <span>}</span><span>)</span><span>;</span>
    <span>}</span>

    <span>return</span> <span>z</span><span>.</span><span>NEVER</span><span>;</span> <span>// The return value is not used, but we need to return something to satisfy the typing</span>
  <span>}</span><span>)</span>
  <span>// here, TS knows that arg is not null</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span><span>arg</span><span>)</span> <span>=&gt;</span> <span>arg</span><span>.</span><span>first</span> <span>===</span> <span>"bob"</span><span>,</span> <span>"`first` is not `bob`!"</span><span>)</span><span>;</span></pre></div>
<blockquote>
<p> You <strong>must</strong> use <code>ctx.addIssue()</code> instead of returning a boolean value to indicate whether the validation passes. If <code>ctx.addIssue</code> is <em>not</em> called during the execution of the function, validation passes.</p>
</blockquote>
<p></p><h3><code>.transform</code></h3><a href="#transform"></a><p></p>
<p>To transform data after parsing, use the <code>transform</code> method.</p>
<div><pre><span>const</span> <span>stringToNumber</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span><span>)</span><span>;</span>

<span>stringToNumber</span><span>.</span><span>parse</span><span>(</span><span>"string"</span><span>)</span><span>;</span> <span>// =&gt; 6</span></pre></div>
<p></p><h4>Chaining order</h4><a href="#chaining-order"></a><p></p>
<p>Note that <code>stringToNumber</code> above is an instance of the <code>ZodEffects</code> subclass. It is NOT an instance of <code>ZodString</code>. If you want to use the built-in methods of <code>ZodString</code> (e.g. <code>.email()</code>) you must apply those methods <em>before</em> any transforms.</p>
<div><pre><span>const</span> <span>emailToDomain</span> <span>=</span> <span>z</span>
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>email</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>split</span><span>(</span><span>"@"</span><span>)</span><span>[</span><span>1</span><span>]</span><span>)</span><span>;</span>

<span>emailToDomain</span><span>.</span><span>parse</span><span>(</span><span>"colinhacks@example.com"</span><span>)</span><span>;</span> <span>// =&gt; example.com</span></pre></div>
<p></p><h4>Validating during transform</h4><a href="#validating-during-transform"></a><p></p>
<p>The <code>.transform</code> method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining <code>transform</code> and <code>refine</code>.</p>
<p>As with <code>.superRefine</code>, the transform function receives a <code>ctx</code> object with an <code>addIssue</code> method that can be used to register validation issues.</p>
<div><pre><span>const</span> <span>numberInString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>,</span> <span>ctx</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>const</span> <span>parsed</span> <span>=</span> <span>parseInt</span><span>(</span><span>val</span><span>)</span><span>;</span>
  <span>if</span> <span>(</span><span>isNaN</span><span>(</span><span>parsed</span><span>)</span><span>)</span> <span>{</span>
    <span>ctx</span><span>.</span><span>addIssue</span><span>(</span><span>{</span>
      <span>code</span>: <span>z</span><span>.</span><span>ZodIssueCode</span><span>.</span><span>custom</span><span>,</span>
      <span>message</span>: <span>"Not a number"</span><span>,</span>
    <span>}</span><span>)</span><span>;</span>

    <span>// This is a special symbol you can use to</span>
    <span>// return early from the transform function.</span>
    <span>// It has type `never` so it does not affect the</span>
    <span>// inferred return type.</span>
    <span>return</span> <span>z</span><span>.</span><span>NEVER</span><span>;</span>
  <span>}</span>
  <span>return</span> <span>parsed</span><span>;</span>
<span>}</span><span>)</span><span>;</span></pre></div>
<p></p><h4>Relationship to refinements</h4><a href="#relationship-to-refinements"></a><p></p>
<p>Transforms and refinements can be interleaved. These will be executed in the order they are declared.</p>
<div><pre><span>const</span> <span>nameToGreeting</span> <span>=</span> <span>z</span>
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>toUpperCase</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span> <span>&gt;</span> <span>15</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>`Hello <span><span>${</span><span>val</span><span>}</span></span>`</span><span>)</span>
  <span>.</span><span>refine</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>indexOf</span><span>(</span><span>"!"</span><span>)</span> <span>===</span> <span>-</span><span>1</span><span>)</span><span>;</span></pre></div>
<p></p><h4>Async transforms</h4><a href="#async-transforms"></a><p></p>
<p>Transforms can also be async.</p>
<div><pre><span>const</span> <span>IdToUser</span> <span>=</span> <span>z</span>
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>uuid</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>async</span> <span>(</span><span>id</span><span>)</span> <span>=&gt;</span> <span>{</span>
    <span>return</span> <span>await</span> <span>getUserById</span><span>(</span><span>id</span><span>)</span><span>;</span>
  <span>}</span><span>)</span><span>;</span></pre></div>
<blockquote>
<p> If your schema contains asynchronous transforms, you must use .parseAsync() or .safeParseAsync() to parse data. Otherwise Zod will throw an error.</p>
</blockquote>
<p></p><h3><code>.default</code></h3><a href="#default"></a><p></p>
<p>You can use transforms to implement the concept of "default values" in Zod.</p>
<div><pre><span>const</span> <span>stringWithDefault</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>default</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span>

<span>stringWithDefault</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; "tuna"</span></pre></div>
<p>Optionally, you can pass a function into <code>.default</code> that will be re-executed whenever a default value needs to be generated:</p>
<div><pre><span>const</span> <span>numberWithRandomDefault</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>default</span><span>(</span><span>Math</span><span>.</span><span>random</span><span>)</span><span>;</span>

<span>numberWithRandomDefault</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.4413456736055323</span>
<span>numberWithRandomDefault</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.1871840107401901</span>
<span>numberWithRandomDefault</span><span>.</span><span>parse</span><span>(</span><span>undefined</span><span>)</span><span>;</span> <span>// =&gt; 0.7223408162401552</span></pre></div>
<p>Conceptually, this is how Zod processes default values:</p>
<ol>
<li>If the input is <code>undefined</code>, the default value is returned</li>
<li>Otherwise, the data is parsed using the base schema</li>
</ol>
<p></p><h3><code>.describe</code></h3><a href="#describe"></a><p></p>
<p>Use <code>.describe()</code> to add a <code>description</code> property to the resulting schema.</p>
<div><pre><span>const</span> <span>documentedString</span> <span>=</span> <span>z</span>
  <span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>describe</span><span>(</span><span>"A useful bit of text, if you know what to do with it."</span><span>)</span><span>;</span>
<span>documentedString</span><span>.</span><span>description</span><span>;</span> <span>// A useful bit of text…</span></pre></div>
<p>This can be useful for documenting a field, for example in a JSON Schema using a library like <a href="https://github.com/StefanTerdell/zod-to-json-schema"><code>zod-to-json-schema</code></a>).</p>
<p></p><h3><code>.catch</code></h3><a href="#catch"></a><p></p>
<p>Use <code>.catch()</code> to provide a "catch value" to be returned in the event of a parsing error.</p>
<div><pre><span>const</span> <span>numberWithCatch</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>catch</span><span>(</span><span>42</span><span>)</span><span>;</span>

<span>numberWithCatch</span><span>.</span><span>parse</span><span>(</span><span>5</span><span>)</span><span>;</span> <span>// =&gt; 5</span>
<span>numberWithCatch</span><span>.</span><span>parse</span><span>(</span><span>"tuna"</span><span>)</span><span>;</span> <span>// =&gt; 42</span></pre></div>
<p>Optionally, you can pass a function into <code>.catch</code> that will be re-executed whenever a default value needs to be generated. A <code>ctx</code> object containing the caught error will be passed into this function.</p>
<div><pre><span>const</span> <span>numberWithRandomCatch</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>catch</span><span>(</span><span>(</span><span>ctx</span><span>)</span> <span>=&gt;</span> <span>{</span>
  <span>ctx</span><span>.</span><span>error</span><span>;</span> <span>// the caught ZodError</span>
  <span>return</span> <span>Math</span><span>.</span><span>random</span><span>(</span><span>)</span><span>;</span>
<span>}</span><span>)</span><span>;</span>

<span>numberWithRandomCatch</span><span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.4413456736055323</span>
<span>numberWithRandomCatch</span><span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.1871840107401901</span>
<span>numberWithRandomCatch</span><span>.</span><span>parse</span><span>(</span><span>"sup"</span><span>)</span><span>;</span> <span>// =&gt; 0.7223408162401552</span></pre></div>
<p>Conceptually, this is how Zod processes "catch values":</p>
<ol>
<li>The data is parsed using the base schema</li>
<li>If the parsing fails, the "catch value" is returned</li>
</ol>
<p></p><h3><code>.optional</code></h3><a href="#optional"></a><p></p>
<p>A convenience method that returns an optional version of a schema.</p>
<div><pre><span>const</span> <span>optionalString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span> <span>// string | undefined</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>optional</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.nullable</code></h3><a href="#nullable"></a><p></p>
<p>A convenience method that returns a nullable version of a schema.</p>
<div><pre><span>const</span> <span>nullableString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>;</span> <span>// string | null</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>nullable</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.nullish</code></h3><a href="#nullish"></a><p></p>
<p>A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both <code>undefined</code> and <code>null</code>. Read more about the concept of "nullish" <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing">in the TypeScript 3.7 release notes</a>.</p>
<div><pre><span>const</span> <span>nullishString</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullish</span><span>(</span><span>)</span><span>;</span> <span>// string | null | undefined</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>nullable</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.array</code></h3><a href="#array"></a><p></p>
<p>A convenience method that returns an array schema for the given type:</p>
<div><pre><span>const</span> <span>stringArray</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>array</span><span>(</span><span>)</span><span>;</span> <span>// string[]</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.promise</code></h3><a href="#promise"></a><p></p>
<p>A convenience method for promise types:</p>
<div><pre><span>const</span> <span>stringPromise</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>promise</span><span>(</span><span>)</span><span>;</span> <span>// Promise&lt;string&gt;</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>promise</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.or</code></h3><a href="#or"></a><p></p>
<p>A convenience method for <a href="#unions">union types</a>.</p>
<div><pre><span>const</span> <span>stringOrNumber</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span> <span>// string | number</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.and</code></h3><a href="#and"></a><p></p>
<p>A convenience method for creating intersection types.</p>
<div><pre><span>const</span> <span>nameAndAge</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span>
  <span>.</span><span>and</span><span>(</span><span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>age</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>;</span> <span>// { name: string } &amp; { age: number }</span>

<span>// equivalent to</span>
<span>z</span><span>.</span><span>intersection</span><span>(</span><span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>age</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>)</span><span>;</span></pre></div>
<p></p><h3><code>.brand</code></h3><a href="#brand"></a><p></p>
<p><code>.brand&lt;T&gt;() =&gt; ZodBranded&lt;this, B&gt;</code></p>
<p>TypeScript's type system is structural, which means that any two types that are structurally equivalent are considered the same.</p>
<div><pre><span>type</span> <span>Cat</span> <span>=</span> <span>{</span> <span>name</span>: <span>string</span> <span>}</span><span>;</span>
<span>type</span> <span>Dog</span> <span>=</span> <span>{</span> <span>name</span>: <span>string</span> <span>}</span><span>;</span>

<span>const</span> <span>petCat</span> <span>=</span> <span>(</span><span>cat</span>: <span>Cat</span><span>)</span> <span>=&gt;</span> <span>{</span><span>}</span><span>;</span>
<span>const</span> <span>fido</span>: <span>Dog</span> <span>=</span> <span>{</span> <span>name</span>: <span>"fido"</span> <span>}</span><span>;</span>
<span>petCat</span><span>(</span><span>fido</span><span>)</span><span>;</span> <span>// works fine</span></pre></div>
<p>In some cases, its can be desirable to simulate <em>nominal typing</em> inside TypeScript. For instance, you may wish to write a function that only accepts an input that has been validated by Zod. This can be achieved with <em>branded types</em> (AKA <em>opaque types</em>).</p>
<div><pre><span>const</span> <span>Cat</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span>brand</span><span>&lt;</span><span>"Cat"</span><span>&gt;</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>Cat</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>Cat</span><span>&gt;</span><span>;</span>

<span>const</span> <span>petCat</span> <span>=</span> <span>(</span><span>cat</span>: <span>Cat</span><span>)</span> <span>=&gt;</span> <span>{</span><span>}</span><span>;</span>

<span>// this works</span>
<span>const</span> <span>simba</span> <span>=</span> <span>Cat</span><span>.</span><span>parse</span><span>(</span><span>{</span> <span>name</span>: <span>"simba"</span> <span>}</span><span>)</span><span>;</span>
<span>petCat</span><span>(</span><span>simba</span><span>)</span><span>;</span>

<span>// this doesn't</span>
<span>petCat</span><span>(</span><span>{</span> <span>name</span>: <span>"fido"</span> <span>}</span><span>)</span><span>;</span></pre></div>
<p>Under the hood, this works by attaching a "brand" to the inferred type using an intersection type. This way, plain/unbranded data structures are no longer assignable to the inferred type of the schema.</p>
<div><pre><span>const</span> <span>Cat</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span>brand</span><span>&lt;</span><span>"Cat"</span><span>&gt;</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>Cat</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>Cat</span><span>&gt;</span><span>;</span>
<span>// {name: string} &amp; {[symbol]: "Cat"}</span></pre></div>
<p>Note that branded types do not affect the runtime result of <code>.parse</code>. It is a static-only construct.</p>
<p></p><h3><code>.readonly</code></h3><a href="#readonly"></a><p></p>
<p><code>.readonly() =&gt; ZodReadonly&lt;this&gt;</code></p>
<p>This method returns a <code>ZodReadonly</code> schema instance that parses the input using the base schema, then calls <code>Object.freeze()</code> on the result. The inferred type is also marked as <code>readonly</code>.</p>
<div><pre><span>const</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span> <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>schema</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>schema</span><span>&gt;</span><span>;</span>
<span>// Readonly&lt;{name: string}&gt;</span>

<span>const</span> <span>result</span> <span>=</span> <span>schema</span><span>.</span><span>parse</span><span>(</span><span>{</span> <span>name</span>: <span>"fido"</span> <span>}</span><span>)</span><span>;</span>
<span>result</span><span>.</span><span>name</span> <span>=</span> <span>"simba"</span><span>;</span> <span>// error</span></pre></div>
<p>The inferred type uses TypeScript's built-in readonly types when relevant.</p>
<div><pre><span>z</span><span>.</span><span>array</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// readonly string[]</span>

<span>z</span><span>.</span><span>tuple</span><span>(</span><span>[</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>]</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// readonly [string, number]</span>

<span>z</span><span>.</span><span>map</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// ReadonlyMap&lt;string, Date&gt;</span>

<span>z</span><span>.</span><span>set</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>readonly</span><span>(</span><span>)</span><span>;</span>
<span>// ReadonlySet&lt;string&gt;</span></pre></div>
<p></p><h3><code>.pipe</code></h3><a href="#pipe"></a><p></p>
<p>Schemas can be chained into validation "pipelines". It's useful for easily validating the result after a <code>.transform()</code>:</p>
<div><pre><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span>
  <span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span><span>)</span>
  <span>.</span><span>pipe</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>min</span><span>(</span><span>5</span><span>)</span><span>)</span><span>;</span></pre></div>
<p>The <code>.pipe()</code> method returns a <code>ZodPipeline</code> instance.</p>
<p></p><h4>You can use <code>.pipe()</code> to fix common issues with <code>z.coerce</code>.</h4><a href="#you-can-use-pipe-to-fix-common-issues-with-zcoerce"></a><p></p>
<p>You can constrain the input to types that work well with your chosen coercion. Then use <code>.pipe()</code> to apply the coercion.</p>
<p>without constrained input:</p>
<div><pre><span>const</span> <span>toDate</span> <span>=</span> <span>z</span><span>.</span><span>coerce</span><span>.</span><span>date</span><span>(</span><span>)</span><span>;</span>

<span>// works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toDate</span><span>.</span><span>safeParse</span><span>(</span><span>"2023-01-01"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>

<span>// might not be what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toDate</span><span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span></pre></div>
<p>with constrained input:</p>
<div><pre><span>const</span> <span>datelike</span> <span>=</span> <span>z</span><span>.</span><span>union</span><span>(</span><span>[</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span> <span>z</span><span>.</span><span>date</span><span>(</span><span>)</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>datelikeToDate</span> <span>=</span> <span>datelike</span><span>.</span><span>pipe</span><span>(</span><span>z</span><span>.</span><span>coerce</span><span>.</span><span>date</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// still works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>datelikeToDate</span><span>.</span><span>safeParse</span><span>(</span><span>"2023-01-01"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>

<span>// more likely what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>datelikeToDate</span><span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// false</span></pre></div>
<p>You can also use this technique to avoid coercions that throw uncaught errors.</p>
<p>without constrained input:</p>
<div><pre><span>const</span> <span>toBigInt</span> <span>=</span> <span>z</span><span>.</span><span>coerce</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>;</span>

<span>// works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toBigInt</span><span>.</span><span>safeParse</span><span>(</span><span>"42"</span><span>)</span><span>)</span><span>;</span> <span>// true</span>

<span>// probably not what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toBigInt</span><span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>)</span><span>;</span> <span>// throws uncaught error</span></pre></div>
<p>with constrained input:</p>
<div><pre><span>const</span> <span>toNumber</span> <span>=</span> <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>.</span><span>pipe</span><span>(</span><span>z</span><span>.</span><span>coerce</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>const</span> <span>toBigInt</span> <span>=</span> <span>z</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>.</span><span>or</span><span>(</span><span>toNumber</span><span>)</span><span>.</span><span>pipe</span><span>(</span><span>z</span><span>.</span><span>coerce</span><span>.</span><span>bigint</span><span>(</span><span>)</span><span>)</span><span>;</span>

<span>// still works intuitively</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toBigInt</span><span>.</span><span>safeParse</span><span>(</span><span>"42"</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// true</span>

<span>// error handled by zod, more likely what you want</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>toBigInt</span><span>.</span><span>safeParse</span><span>(</span><span>null</span><span>)</span><span>.</span><span>success</span><span>)</span><span>;</span> <span>// false</span></pre></div>
<p></p><h2>Guides and concepts</h2><a href="#guides-and-concepts"></a><p></p>
<p></p><h3>Type inference</h3><a href="#type-inference"></a><p></p>
<p>You can extract the TypeScript type of any schema with <code>z.infer&lt;typeof mySchema&gt;</code> .</p>
<div><pre><span>const</span> <span>A</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>;</span>
<span>type</span> <span>A</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>A</span><span>&gt;</span><span>;</span> <span>// string</span>

<span>const</span> <span>u</span>: <span>A</span> <span>=</span> <span>12</span><span>;</span> <span>// TypeError</span>
<span>const</span> <span>u</span>: <span>A</span> <span>=</span> <span>"asdf"</span><span>;</span> <span>// compiles</span></pre></div>
<p><strong>What about transforms?</strong></p>
<p>In reality each Zod schema internally tracks <strong>two</strong> types: an input and an output. For most schemas (e.g. <code>z.string()</code>) these two are the same. But once you add transforms into the mix, these two values can diverge. For instance <code>z.string().transform(val =&gt; val.length)</code> has an input of <code>string</code> and an output of <code>number</code>.</p>
<p>You can separately extract the input and output types like so:</p>
<div><pre><span>const</span> <span>stringToNumber</span> <span>=</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>.</span><span>transform</span><span>(</span><span>(</span><span>val</span><span>)</span> <span>=&gt;</span> <span>val</span><span>.</span><span>length</span><span>)</span><span>;</span>

<span>// ⚠️ Important: z.infer returns the OUTPUT type!</span>
<span>type</span> <span>input</span> <span>=</span> <span>z</span><span>.</span><span>input</span><span>&lt;</span><span>typeof</span> <span>stringToNumber</span><span>&gt;</span><span>;</span> <span>// string</span>
<span>type</span> <span>output</span> <span>=</span> <span>z</span><span>.</span><span>output</span><span>&lt;</span><span>typeof</span> <span>stringToNumber</span><span>&gt;</span><span>;</span> <span>// number</span>

<span>// equivalent to z.output!</span>
<span>type</span> <span>inferred</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>stringToNumber</span><span>&gt;</span><span>;</span> <span>// number</span></pre></div>
<p></p><h3>Writing generic functions</h3><a href="#writing-generic-functions"></a><p></p>
<p>With TypeScript generics, you can write reusable functions that accept Zod schemas as parameters. This enables you to create custom validation logic, schema transformations, and more, while maintaining type safety and inference.</p>
<p>When attempting to write a function that accepts a Zod schema as an input, it's tempting to try something like this:</p>
<div><pre><span>function</span> <span>inferSchema</span><span>&lt;</span><span>T</span><span>&gt;</span><span>(</span><span>schema</span>: <span>z</span><span>.</span><span>ZodType</span><span>&lt;</span><span>T</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>return</span> <span>schema</span><span>;</span>
<span>}</span></pre></div>
<p>This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of <code>schema</code> will be an instance of <code>ZodType</code>.</p>
<div><pre><span>inferSchema</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; ZodType&lt;string&gt;</span></pre></div>
<p>This approach loses type information, namely <em>which subclass</em> the input actually is (in this case, <code>ZodString</code>). That means you can't call any string-specific methods like <code>.min()</code> on the result of <code>inferSchema</code>.</p>
<p>A better approach is to infer <em>the schema as a whole</em> instead of merely its inferred type. You can do this with a utility type called <code>z.ZodTypeAny</code>.</p>
<div><pre><span>function</span> <span>inferSchema</span><span>&lt;</span><span>T</span> <span>extends</span> <span>z</span><span>.</span><span>ZodTypeAny</span><span>&gt;</span><span>(</span><span>schema</span>: <span>T</span><span>)</span> <span>{</span>
  <span>return</span> <span>schema</span><span>;</span>
<span>}</span>

<span>inferSchema</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; ZodString</span></pre></div>
<blockquote>
<p><code>ZodTypeAny</code> is just a shorthand for <code>ZodType&lt;any, any, any&gt;</code>, a type that is broad enough to match any Zod schema.</p>
</blockquote>
<p>The Result is now fully and properly typed, and the type system can infer the specific subclass of the schema.</p>
<p></p><h4>Inferring the inferred type</h4><a href="#inferring-the-inferred-type"></a><p></p>
<p>If you follow the best practice of using <code>z.ZodTypeAny</code> as the generic parameter for your schema, you may encounter issues with the parsed data being typed as <code>any</code> instead of the inferred type of the schema.</p>
<div><pre><span>function</span> <span>parseData</span><span>&lt;</span><span>T</span> <span>extends</span> <span>z</span><span>.</span><span>ZodTypeAny</span><span>&gt;</span><span>(</span><span>data</span>: <span>unknown</span><span>,</span> <span>schema</span>: <span>T</span><span>)</span> <span>{</span>
  <span>return</span> <span>schema</span><span>.</span><span>parse</span><span>(</span><span>data</span><span>)</span><span>;</span>
<span>}</span>

<span>parseData</span><span>(</span><span>"sup"</span><span>,</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; any</span></pre></div>
<p>Due to how TypeScript inference works, it is treating <code>schema</code> like a <code>ZodTypeAny</code> instead of the inferred type. You can fix this with a type cast using <code>z.infer</code>.</p>
<div><pre><span>function</span> <span>parseData</span><span>&lt;</span><span>T</span> <span>extends</span> <span>z</span><span>.</span><span>ZodTypeAny</span><span>&gt;</span><span>(</span><span>data</span>: <span>unknown</span><span>,</span> <span>schema</span>: <span>T</span><span>)</span> <span>{</span>
  <span>return</span> <span>schema</span><span>.</span><span>parse</span><span>(</span><span>data</span><span>)</span> <span>as</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>T</span><span>&gt;</span><span>;</span>
  <span>//                        ^^^^^^^^^^^^^^ &lt;- add this</span>
<span>}</span>

<span>parseData</span><span>(</span><span>"sup"</span><span>,</span> <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// =&gt; string</span></pre></div>
<p></p><h4>Constraining allowable inputs</h4><a href="#constraining-allowable-inputs"></a><p></p>
<p>The <code>ZodType</code> class has three generic parameters.</p>
<div><pre><span>class</span> <span>ZodType</span><span>&lt;</span>
  <span>Output</span> <span>=</span> <span>any</span><span>,</span>
  <span>Def</span> <span>extends</span> <span>ZodTypeDef</span> <span>=</span> <span>ZodTypeDef</span><span>,</span>
  <span>Input</span> <span>=</span> <span>Output</span>
<span>&gt;</span> <span>{</span> ... <span>}</span></pre></div>
<p>By constraining these in your generic input, you can limit what schemas are allowable as inputs to your function:</p>
<div><pre><span>function</span> <span>makeSchemaOptional</span><span>&lt;</span><span>T</span> <span>extends</span> <span>z</span><span>.</span><span>ZodType</span><span>&lt;</span><span>string</span><span>&gt;</span><span>&gt;</span><span>(</span><span>schema</span>: <span>T</span><span>)</span> <span>{</span>
  <span>return</span> <span>schema</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>;</span>
<span>}</span>

<span>makeSchemaOptional</span><span>(</span><span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// works fine</span>

<span>makeSchemaOptional</span><span>(</span><span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span><span>;</span>
<span>// Error: 'ZodNumber' is not assignable to parameter of type 'ZodType&lt;string, ZodTypeDef, string&gt;'</span></pre></div>
<p></p><h3>Error handling</h3><a href="#error-handling"></a><p></p>
<p>Zod provides a subclass of Error called <code>ZodError</code>. ZodErrors contain an <code>issues</code> array containing detailed information about the validation problems.</p>
<div><pre><span>const</span> <span>result</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>safeParse</span><span>(</span><span>{</span> <span>name</span>: <span>12</span> <span>}</span><span>)</span><span>;</span>

<span>if</span> <span>(</span><span>!</span><span>result</span><span>.</span><span>success</span><span>)</span> <span>{</span>
  <span>result</span><span>.</span><span>error</span><span>.</span><span>issues</span><span>;</span>
  <span>/* [</span>
<span>      {</span>
<span>        "code": "invalid_type",</span>
<span>        "expected": "string",</span>
<span>        "received": "number",</span>
<span>        "path": [ "name" ],</span>
<span>        "message": "Expected string, received number"</span>
<span>      }</span>
<span>  ] */</span>
<span>}</span></pre></div>
<blockquote>
<p>For detailed information about the possible error codes and how to customize error messages, check out the dedicated error handling guide: <a href="https://github.com/colinhacks/zod/blob/main/ERROR_HANDLING.md">ERROR_HANDLING.md</a></p>
</blockquote>
<p>Zod's error reporting emphasizes <em>completeness</em> and <em>correctness</em>. 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 <a href="https://github.com/causaly/zod-validation-error"><code>zod-validation-error</code></a></p>
<p></p><h3>Error formatting</h3><a href="#error-formatting"></a><p></p>
<p>You can use the <code>.format()</code> method to convert this error into a nested object.</p>
<div><pre><span>const</span> <span>result</span> <span>=</span> <span>z</span>
  <span>.</span><span>object</span><span>(</span><span>{</span>
    <span>name</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
  <span>.</span><span>safeParse</span><span>(</span><span>{</span> <span>name</span>: <span>12</span> <span>}</span><span>)</span><span>;</span>

<span>if</span> <span>(</span><span>!</span><span>result</span><span>.</span><span>success</span><span>)</span> <span>{</span>
  <span>const</span> <span>formatted</span> <span>=</span> <span>result</span><span>.</span><span>error</span><span>.</span><span>format</span><span>(</span><span>)</span><span>;</span>
  <span>/* {</span>
<span>    name: { _errors: [ 'Expected string, received number' ] }</span>
<span>  } */</span>

  <span>formatted</span><span>.</span><span>name</span><span>?.</span><span>_errors</span><span>;</span>
  <span>// =&gt; ["Expected string, received number"]</span>
<span>}</span></pre></div>
<p></p><h2>Comparison</h2><a href="#comparison"></a><p></p>
<p>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.</p>



<p></p><h3>Joi</h3><a href="#joi"></a><p></p>
<p><a href="https://github.com/hapijs/joi">https://github.com/hapijs/joi</a></p>
<p>Doesn't support static type inference 😕</p>
<p></p><h3>Yup</h3><a href="#yup"></a><p></p>
<p><a href="https://github.com/jquense/yup">https://github.com/jquense/yup</a></p>
<p>Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.</p>
<ul>
<li>Supports casting and transforms</li>
<li>All object fields are optional by default</li>
</ul>

<ul>
<li>Missing promise schemas</li>
<li>Missing function schemas</li>
<li>Missing union &amp; intersection schemas</li>
</ul>

<p></p><h3>io-ts</h3><a href="#io-ts"></a><p></p>
<p><a href="https://github.com/gcanti/io-ts">https://github.com/gcanti/io-ts</a></p>
<p>io-ts is an excellent library by gcanti. The API of io-ts heavily inspired the design of Zod.</p>
<p>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:</p>
<div><pre><span>import</span> <span>*</span> <span>as</span> <span>t</span> <span>from</span> <span>"io-ts"</span><span>;</span>

<span>const</span> <span>A</span> <span>=</span> <span>t</span><span>.</span><span>type</span><span>(</span><span>{</span>
  <span>foo</span>: <span>t</span><span>.</span><span>string</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>B</span> <span>=</span> <span>t</span><span>.</span><span>partial</span><span>(</span><span>{</span>
  <span>bar</span>: <span>t</span><span>.</span><span>number</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>const</span> <span>C</span> <span>=</span> <span>t</span><span>.</span><span>intersection</span><span>(</span><span>[</span><span>A</span><span>,</span> <span>B</span><span>]</span><span>)</span><span>;</span>

<span>type</span> <span>C</span> <span>=</span> <span>t</span><span>.</span><span>TypeOf</span><span>&lt;</span><span>typeof</span> <span>C</span><span>&gt;</span><span>;</span>
<span>// returns { foo: string; bar?: number | undefined }</span></pre></div>
<p>You must define the required and optional props in separate object validators, pass the optionals through <code>t.partial</code> (which marks all properties as optional), then combine them with <code>t.intersection</code> .</p>
<p>Consider the equivalent in Zod:</p>
<div><pre><span>const</span> <span>C</span> <span>=</span> <span>z</span><span>.</span><span>object</span><span>(</span><span>{</span>
  <span>foo</span>: <span>z</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>bar</span>: <span>z</span><span>.</span><span>number</span><span>(</span><span>)</span><span>.</span><span>optional</span><span>(</span><span>)</span><span>,</span>
<span>}</span><span>)</span><span>;</span>

<span>type</span> <span>C</span> <span>=</span> <span>z</span><span>.</span><span>infer</span><span>&lt;</span><span>typeof</span> <span>C</span><span>&gt;</span><span>;</span>
<span>// returns { foo: string; bar?: number | undefined }</span></pre></div>
<p>This more declarative API makes schema definitions vastly more concise.</p>
<p><code>io-ts</code> also requires the use of gcanti's functional programming library <code>fp-ts</code> to parse results and handle errors. This is another fantastic resource for developers looking to keep their codebase strictly functional. But depending on <code>fp-ts</code> necessarily comes with a lot of intellectual overhead; a developer has to be familiar with functional programming concepts and the <code>fp-ts</code> nomenclature to use the library.</p>
<ul>
<li>Supports codecs with serialization &amp; deserialization transforms</li>
<li>Supports branded types</li>
<li>Supports advanced functional programming, higher-kinded types, <code>fp-ts</code> compatibility</li>
<li>Missing object methods: (pick, omit, partial, deepPartial, merge, extend)</li>
<li>Missing nonempty arrays with proper typing (<code>[T, ...T[]]</code>)</li>
<li>Missing promise schemas</li>
<li>Missing function schemas</li>
</ul>
<p></p><h3>Runtypes</h3><a href="#runtypes"></a><p></p>
<p><a href="https://github.com/pelotom/runtypes">https://github.com/pelotom/runtypes</a></p>
<p>Good type inference support.</p>
<ul>
<li>Supports "pattern matching": computed properties that distribute over unions</li>
<li>Missing object methods: (deepPartial, merge)</li>
<li>Missing nonempty arrays with proper typing (<code>[T, ...T[]]</code>)</li>
<li>Missing promise schemas</li>
<li>Missing error customization</li>
</ul>
<p></p><h3>Ow</h3><a href="#ow"></a><p></p>
<p><a href="https://github.com/sindresorhus/ow">https://github.com/sindresorhus/ow</a></p>
<p>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 (e.g. <code>int32Array</code> , see full list in their README).</p>
<p>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.</p>
<p></p><h2>Changelog</h2><a href="#changelog"></a><p></p>
<p>View the changelog at <a href="https://github.com/colinhacks/zod/blob/main/CHANGELOG.md">CHANGELOG.md</a></p>
</article></div></div>||||I||||    Skip to content

    Navigation Menu

    Toggle navigation
          Sign in
            * Product
                        + Actions
                        Automate any workflow
                        + Packages
                        Host and manage packages
                        + Security
                        Find and fix vulnerabilities
                        + Codespaces
                        Instant dev environments
                        + GitHub Copilot
                        Write better code with AI
                        + Code review
                        Manage code changes
                        + Issues
                        Plan and track work
                        + Discussions
                        Collaborate outside of code
                  Explore
                    + All features
                    + Documentation
                    + GitHub Skills
                    + Blog
            * Solutions
                  By size
                    + Enterprise
                    + Teams
                    + Startups
                  By industry
                    + Healthcare
                    + Financial services
                    + Manufacturing
                  By use case
                    + CI/CD & Automation
                    + DevOps
                    + DevSecOps
            * Resources
                  Topics
                    + AI
                    + DevOps
                    + Security
                    + Software Development
                  Explore
                    + Learning Pathways
                    + White papers, Ebooks, Webinars
                    + Customer Stories
                    + Partners
            * Open Source
                        + GitHub Sponsors
                        Fund open source developers
                        + The ReadME Project
                        GitHub community articles
                  Repositories
                    + Topics
                    + Trending
                    + Collections
            * Enterprise
                        + Enterprise platform
                        AI-powered developer platform
                  Available add-ons
                        + Advanced Security
                        Enterprise-grade security features
                        + GitHub Copilot
                        Enterprise-grade AI features
                        + Premium Support
                        Enterprise-grade 24/7 support
            * Pricing
              Search or jump to...

                Search code, repositories, users, issues, pull requests...

                        Search
                          Clear
                        Search syntax tips

                    Provide feedback

                We read every piece of feedback, and take your input very seriously.

                Include my email address so I can be contacted
                Cancel Submit feedback

                    Saved searches

                    Use saved searches to filter your results more quickly

                    Name
                    Query

                  To see all available qualifiers, see our documentation.

                Cancel Create saved search
              Sign in
            Sign up Reseting focus
      You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert
            {{ message }}
              colinhacks / zod Public
              * 
              * Notifications You must be signed in to change notification settings
              * Fork 1.1k
                * Star 32.5k

            TypeScript-first schema validation with static type inference

              zod.dev

            License

              MIT license
              32.5k stars 1.1k forks Branches Tags Activity
                  Star
                Notifications You must be signed in to change notification settings
          * Code
          * Issues 379
          * Pull requests 40
          * Discussions
          * Actions
          * Projects 0
          * Security
          * Insights
          Additional navigation options
                  * Code
                  * Issues
                  * Pull requests
                  * Discussions
                  * Actions
                  * Projects
                  * Security
                  * Insights

        colinhacks/zod

                  This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
                              main
                          Branches Tags
                            Go to file
                        Code

                        Folders and files

                          Name                            Name                              Last commit message    Last commit date
                            Latest commit               
                                                        
                                History                 
                                                        
                                2,059 Commits           
                                  .devcontainer                   .devcontainer                                                    
                                  .github/ workflows              .github/ workflows                                               
                                  .husky                          .husky                                                           
                                  .vscode                         .vscode                                                          
                                  blog                            blog                                                             
                                  configs                         configs                                                          
                                  deno/ lib                       deno/ lib                                                        
                                  src                             src                                                              
                                  static                          static                                                           
                                  .dependency-cruiser.js          .dependency-cruiser.js                                           
                                  .editorconfig                   .editorconfig                                                    
                                  .eslintignore                   .eslintignore                                                    
                                  .eslintrc.js                    .eslintrc.js                                                     
                                  .gitignore                      .gitignore                                                       
                                  .nojekyll                       .nojekyll                                                        
                                  .prettierrc.yaml                .prettierrc.yaml                                                 
                                  CHANGELOG.md                    CHANGELOG.md                                                     
                                  CODE_OF_CONDUCT.md              CODE_OF_CONDUCT.md                                               
                                  CONTRIBUTING.md                 CONTRIBUTING.md                                                  
                                  ERROR_HANDLING.md               ERROR_HANDLING.md                                                
                                  FUNDING.yml                     FUNDING.yml                                                      
                                  LICENSE                         LICENSE                                                          
                                  MIGRATION.md                    MIGRATION.md                                                     
                                  README.md                       README.md                                                        
                                  README_ZH.md                    README_ZH.md                                                     
                                  _redirects                      _redirects                                                       
                                  deno-build.mjs                  deno-build.mjs                                                   
                                  index.d.ts                      index.d.ts                                                       
                                  index.html                      index.html                                                       
                                  jest.config.json                jest.config.json                                                 
                                  logo.svg                        logo.svg                                                         
                                  package.json                    package.json                                                     
                                  playground.ts                   playground.ts                                                    
                                  robots.txt                      robots.txt                                                       
                                  tsconfig.json                   tsconfig.json                                                    
                                  yarn.lock                       yarn.lock                                                        
                            View all files              
                          

                              Repository files navigation

                                * README
                                * Code of conduct
                                * MIT license

                                Zod

                              ✨ https://zod.dev ✨
                              TypeScript-first schema validation with static type inference


                                Documentation • Discord • npm • deno • Issues • @colinhacks • tRPC




                                Table of contents

                              These docs have been translated into Chinese.

                                * Table of contents
                                * Introduction
                                    + Sponsors
                                        o Platinum
                                        o Gold
                                        o Silver
                                        o Bronze
                                        o Copper
                                    + Ecosystem
                                        o Resources
                                        o API libraries
                                        o Form integrations
                                        o Zod to X
                                        o X to Zod
                                        o Mocking
                                        o Powered by Zod
                                        o Utilities for Zod
                                * Installation
                                    + Requirements
                                    + From npm (Node/Bun)
                                    + From deno.land/x (Deno)
                                * Basic usage
                                * Primitives
                                * Coercion for primitives
                                * Literals
                                * Strings
                                    + Datetimes
                                    + Dates
                                    + Times
                                    + IP addresses
                                * Numbers
                                * BigInts
                                * NaNs
                                * Booleans
                                * Dates
                                * Zod enums
                                * Native enums
                                * Optionals
                                * Nullables
                                * Objects
                                    + .shape
                                    + .keyof
                                    + .extend
                                    + .merge
                                    + .pick/.omit
                                    + .partial
                                    + .deepPartial
                                    + .required
                                    + .passthrough
                                    + .strict
                                    + .strip
                                    + .catchall
                                * Arrays
                                    + .element
                                    + .nonempty
                                    + .min/.max/.length
                                * Tuples
                                * Unions
                                * Discriminated unions
                                * Records
                                    + Record key type
                                * Maps
                                * Sets
                                * Intersections
                                * Recursive types
                                    + ZodType with ZodEffects
                                    + JSON type
                                    + Cyclical objects
                                * Promises
                                * Instanceof
                                * Functions
                                * Preprocess
                                * Custom schemas
                                * Schema methods
                                    + .parse
                                    + .parseAsync
                                    + .safeParse
                                    + .safeParseAsync
                                    + .refine
                                        o Arguments
                                        o Customize error path
                                        o Asynchronous refinements
                                        o Relationship to transforms
                                    + .superRefine
                                        o Abort early
                                        o Type refinements
                                    + .transform
                                        o Chaining order
                                        o Validating during transform
                                        o Relationship to refinements
                                        o Async transforms
                                    + .default
                                    + .describe
                                    + .catch
                                    + .optional
                                    + .nullable
                                    + .nullish
                                    + .array
                                    + .promise
                                    + .or
                                    + .and
                                    + .brand
                                    + .readonly
                                    + .pipe
                                        o You can use .pipe() to fix common issues with z.coerce.
                                * Guides and concepts
                                    + Type inference
                                    + Writing generic functions
                                        o Constraining allowable inputs
                                    + Error handling
                                    + Error formatting
                                * Comparison
                                    + Joi
                                    + Yup
                                    + io-ts
                                    + Runtypes
                                    + Ow
                                * Changelog

                                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
                                * Works with plain JavaScript too! You don't need to use TypeScript.

                                Sponsors

                              Sponsorship at any level is appreciated and encouraged. If you built a paid product using Zod, consider one of the corporate tiers.


                                Diamond




                                The most comprehensive User Management Platform
                                clerk.com



                                Platinum

                                                                        
                                  Serverless Postgres — Ship faster     
                                              neon.tech                 
                                                                        
                                                                        
                              Build AI apps and workflows with Retool AI
                                              retool.com                
                                                                        
                                                                        
                                     Generate best-in-class SDKs        
                                           stainlessapi.com             
                                                                        
                                                                        
                               SDKs & Terraform providers for your API  
                                            speakeasy.com               
                                                                        
                              


                                Gold

                                                                               
                              PropelAuth    Cerbos     Scalar     Trigger.dev  
                                                                               
                              Transloadit  Infisical    Whop     CryptoJobsList
                                                                               
                                Plain.      Inngest   Storyblok       Mux      
                              


                                Silver

                                    
                                    
                              
                              

                                Bronze

                              Brandon Bayer  Jiří Brabec     Alex Johansson       Fungible Systems         
                              Adaptable      Avana Wallet    Jason Lengstorf      Global Illumination, Inc.
                              MasterBorn     Ryan Palmer     Michael Sweeney      Nextbase                 
                              Remotion       Connor Sinnott  Mohammad-Ali A'râbi  Supatool                 
                              

                                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 or start a Discussion. I'll add it below and tweet it out.

                                Resources

                                * Total TypeScript Zod Tutorial by @mattpocockuk
                                * Fixing TypeScript's Blindspot: Runtime Typechecking by @jherr

                                API libraries

                                * tRPC: Build end-to-end typesafe APIs without GraphQL.
                                * @anatine/zod-nestjs: Helper methods for using Zod in a NestJS project.
                                * zod-endpoints: Contract-first strictly typed endpoints with Zod. OpenAPI compatible.
                                * zhttp: An OpenAPI compatible, strictly typed http library with Zod input and response validation.
                                * 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: A typescript API client with runtime and compile time validation backed by axios and zod.
                                * express-zod-api: Build Express-based APIs with I/O schema validation and custom middlewares.
                                * tapiduck: End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler.
                                * koa-zod-router: Create typesafe routes in Koa with I/O validation using Zod.
                                * zod-sockets: Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs

                                Form integrations

                                * react-hook-form: A first-party Zod resolver for React Hook Form.
                                * zod-validation-error: Generate user-friendly error messages from ZodErrors.
                                * zod-formik-adapter: A community-maintained Formik adapter for Zod.
                                * react-zorm: Standalone <form> generation and validation for React using Zod.
                                * zodix: Zod utilities for FormData and URLSearchParams in Remix loaders and actions.
                                * conform: A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js.
                                * remix-params-helper: Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.
                                * formik-validator-zod: Formik-compliant validator library that simplifies using Zod with Formik.
                                * zod-i18n-map: Useful for translating Zod error messages.
                                * @modular-forms/solid: Modular form library for SolidJS that supports Zod for validation.
                                * houseform: A React form library that uses Zod for validation.
                                * sveltekit-superforms: Supercharged form library for SvelteKit with Zod validation.
                                * mobx-zod-form: Data-first form builder based on MobX & Zod.
                                * @vee-validate/zod: Form library for Vue.js with Zod schema validation.

                                Zod to X

                                * zod-to-ts: Generate TypeScript definitions from Zod schemas.
                                * zod-to-json-schema: Convert your Zod schemas into JSON Schemas.
                                * @anatine/zod-openapi: Converts a Zod schema to an OpenAPI v3.x SchemaObject.
                                * zod-fast-check: Generate fast-check arbitraries from Zod schemas.
                                * zod-dto: Generate Nest.js DTOs from a Zod schema.
                                * fastify-type-provider-zod: Create Fastify type providers from Zod schemas.
                                * zod-to-openapi: Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters.
                                * nestjs-graphql-zod: Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.
                                * zod-openapi: Create full OpenAPI v3.x documentation from Zod schemas.
                                * fastify-zod-openapi: Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas.
                                * typeschema: Universal adapter for schema validation.

                                X to Zod

                                * ts-to-zod: Convert TypeScript definitions into Zod schemas.
                                * @runtyping/zod: Generate Zod from static types & JSON schema.
                                * json-schema-to-zod: Convert your JSON Schemas into Zod schemas. Live demo.
                                * json-to-zod: Convert JSON objects into Zod schemas. Live demo.
                                * graphql-codegen-typescript-validation-schema: GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.
                                * zod-prisma: Generate Zod schemas from your Prisma schema.
                                * Supervillain: Generate Zod schemas from your Go structs.
                                * prisma-zod-generator: Emit Zod schemas from your Prisma schema.
                                * drizzle-zod: Emit Zod schemas from your Drizzle schema.
                                * prisma-trpc-generator: Emit fully implemented tRPC routers and their validation schemas using Zod.
                                * zod-prisma-types Create Zod types from your Prisma models.
                                * quicktype: Convert JSON objects and JSON schemas into Zod schemas.
                                * @sanity-typed/zod: Generate Zod Schemas from Sanity Schemas.
                                * java-to-zod: Convert POJOs to Zod schemas
                                * Orval: Generate Zod schemas from OpenAPI schemas
                                * Kubb: Generate SDKs and Zod schemas from your OpenAPI schemas

                                Mocking

                                * @anatine/zod-mock: Generate mock data from a Zod schema. Powered by faker.js.
                                * zod-mocking: Generate mock data from your Zod schemas.
                                * zod-fixture: Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.
                                * zocker: Generate plausible mock-data from your schemas.
                                * zodock Generate mock data based on Zod schemas.
                                * zod-schema-faker Generates mock data from Zod schemas. Powered by @faker-js/faker and randexp.js

                                Powered by Zod

                                * freerstore: Firestore cost optimizer.
                                * slonik: Node.js Postgres client with strong Zod integration.
                                * soly: Create CLI applications with zod.
                                * pastel: Create CLI applications with react, zod, and ink.
                                * zod-xlsx: A xlsx based resource validator using Zod schemas.
                                * znv: Type-safe environment parsing and validation for Node.js with Zod schemas.
                                * zod-config: Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.

                                Utilities for Zod

                                * zod_utilz: Framework agnostic utilities for Zod.
                                * zod-playground: A tool for learning and testing Zod schema validation functionalities. Link.
                                * zod-sandbox: Controlled environment for testing zod schemas. Live demo.
                                * zod-dev: Conditionally disables Zod runtime parsing in production.
                                * zod-accelerator: Accelerates Zod's throughput up to ~100x.

                                Installation

                                Requirements

                                * TypeScript 4.5+!

                                * You must enable strict mode in your tsconfig.json. This is a best practice for all TypeScript projects.

                                    // tsconfig.json
                                    {
                                      // ...
                                      "compilerOptions": {
                                        // ...
                                        "strict": true
                                      }
                                    }

                                From npm (Node/Bun)

                                npm install zod       # npm
                                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:

                                npm install zod@canary       # npm
                                yarn add zod@canary          # yarn
                                bun add zod@canary           # bun
                                pnpm add zod@canary          # pnpm

                                From deno.land/x (Deno)

                              Unlike Node, Deno relies on direct URL imports instead of a package manager like NPM. Zod is available on deno.land/x. The latest version can be imported like so:

                                import { z } from "https://deno.land/x/zod/mod.ts";

                              You can also specify a particular version:

                                import { z } from "https://deno.land/x/zod@v3.16.1/mod.ts";

                              The rest of this README assumes you are using npm and importing directly from the "zod" package.

                                Basic usage

                              Creating a simple string schema

                                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

                                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 }

                                Primitives

                                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();

                                Coercion for primitives

                              Zod now provides a more convenient way to coerce primitive values.

                                const schema = z.coerce.string();
                                schema.parse("tuna"); // => "tuna"
                                schema.parse(12); // => "12"

                              During the parsing step, the input is passed through the String() function, which is a JavaScript built-in for coercing data into strings.

                                schema.parse(12); // => "12"
                                schema.parse(true); // => "true"
                                schema.parse(undefined); // => "undefined"
                                schema.parse(null); // => "null"

                              The returned schema is a normal ZodString instance so you can use all string methods.

                                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.

                                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 value is coerced to true, and any falsy value is coerced to 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

                              For more control over coercion logic, consider using z.preprocess or z.pipe().

                                Literals

                              Literal schemas represent a literal type, like "hello world" or 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"

                              Currently there is no support for Date literals in Zod. If you have a use case for this feature, please file an issue.

                                Strings

                              Zod includes a handful of string-specific validations.

                                // 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();

                              Check out validator.js for a bunch of other useful string validation functions that can be used in conjunction with Refinements.

                              You can customize some common error messages when creating a string schema.

                                const name = z.string({
                                  required_error: "Name is required",
                                  invalid_type_error: "Name must be a string",
                                });

                              When using validation methods, you can pass in an additional argument to provide a custom error message.

                                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" });

                                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.

                                const datetime = z.string().datetime();
                                
                                datetime.parse("2020-01-01T00:00:00Z"); // pass
                                datetime.parse("2020-01-01T00:00:00.123Z"); // pass
                                datetime.parse("2020-01-01T00:00:00.123456Z"); // pass (arbitrary precision)
                                datetime.parse("2020-01-01T00:00:00+02:00"); // fail (no offsets allowed)

                              Timezone offsets can be allowed by setting the offset option to true.

                                const datetime = z.string().datetime({ offset: true });
                                
                                datetime.parse("2020-01-01T00:00:00+02:00"); // pass
                                datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional)
                                datetime.parse("2020-01-01T00:00:00.123+0200"); // pass (millis optional)
                                datetime.parse("2020-01-01T00:00:00.123+02"); // pass (only offset hours)
                                datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported)

                              You can additionally constrain the allowable precision. By default, arbitrary sub-second precision is supported (but optional).

                                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

                                Dates

                              Added in Zod 3.23

                              The z.string().date() method validates strings in the format 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

                                Times

                              Added in Zod 3.23

                              The z.string().time() method validates strings in the format HH:MM:SS[.s+]. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind.

                                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)

                              You can set the precision option to constrain the allowable decimal 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

                                IP addresses

                              The z.string().ip() method by default validate IPv4 and 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

                              You can additionally set the 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

                                Numbers

                              You can customize certain error messages when creating a number schema.

                                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.

                                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.

                                z.number().lte(5, { message: "this👏is👏too👏big" });

                                BigInts

                              Zod includes a handful of bigint-specific validations.

                                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.

                                NaNs

                              You can customize certain error messages when creating a nan schema.

                                const isNaN = z.nan({
                                  required_error: "isNaN is required",
                                  invalid_type_error: "isNaN must be 'not a number'",
                                });

                                Booleans

                              You can customize certain error messages when creating a boolean schema.

                                const isActive = z.boolean({
                                  required_error: "isActive is required",
                                  invalid_type_error: "isActive must be a boolean",
                                });

                                Dates

                              Use z.date() to validate Date instances.

                                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.

                                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.

                                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, use z.coerce.date() to pass the input through 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

                              For older zod versions, use z.preprocess like described in this thread.

                                Zod enums

                                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 for details.

                                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.

                                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:

                                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:

                                FishEnum.options; // ["Salmon", "Tuna", "Trout"];

                              .exclude/.extract()

                              You can create subsets of a Zod enum with the .exclude and .extract methods.

                                const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]);
                                const SalmonAndTrout = FishEnum.extract(["Salmon", "Trout"]);
                                const TunaOnly = FishEnum.exclude(["Salmon", "Trout"]);

                                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

                                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

                                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+!

                                const Fruits = {
                                  Apple: "apple",
                                  Banana: "banana",
                                  Cantaloupe: 3,
                                } as const;
                                
                                const FruitEnum = z.nativeEnum(Fruits);
                                type FruitEnum = z.infer<typeof FruitEnum>; // "apple" | "banana" | 3
                                
                                FruitEnum.parse("apple"); // passes
                                FruitEnum.parse("banana"); // passes
                                FruitEnum.parse(3); // passes
                                FruitEnum.parse("Cantaloupe"); // fails

                              You can access the underlying object with the .enum property:

                                FruitEnum.enum.Apple; // "apple"

                                Optionals

                              You can make any schema optional with z.optional(). This wraps the schema in a ZodOptional instance and returns the result.

                                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.

                                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().

                                const stringSchema = z.string();
                                const optionalString = stringSchema.optional();
                                optionalString.unwrap() === stringSchema; // true

                                Nullables

                              Similarly, you can create nullable types with z.nullable().

                                const nullableString = z.nullable(z.string());
                                nullableString.parse("asdf"); // => "asdf"
                                nullableString.parse(null); // => null

                              Or use the .nullable() method.

                                const E = z.string().nullable(); // equivalent to nullableString
                                type E = z.infer<typeof E>; // string | null

                              Extract the inner schema with .unwrap().

                                const stringSchema = z.string();
                                const nullableString = stringSchema.nullable();
                                nullableString.unwrap() === stringSchema; // true

                                Objects

                                // 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

                              Use .shape to access the schemas for a particular key.

                                Dog.shape.name; // => string schema
                                Dog.shape.age; // => number schema

                                .keyof

                              Use .keyof to create a ZodEnum schema from the keys of an object schema.

                                const keySchema = Dog.keyof();
                                keySchema; // ZodEnum<["name", "age"]>

                                .extend

                              You can add additional fields to an object schema with the .extend method.

                                const DogWithBreed = Dog.extend({
                                  breed: z.string(),
                                });

                              You can use .extend to overwrite fields! Be careful with this power!

                                .merge

                              Equivalent to 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 }

                              If the two schemas share keys, the properties of B overrides the property of A. The returned schema also inherits the "unknownKeys" policy (strip/strict/passthrough) and the catchall schema of B.

                                .pick/.omit

                              Inspired by TypeScript's built-in Pick and Omit utility types, all Zod object schemas have .pick and .omit methods that return a modified version. Consider this Recipe schema:

                                const Recipe = z.object({
                                  id: z.string(),
                                  name: z.string(),
                                  ingredients: z.array(z.string()),
                                });

                              To only keep certain keys, use .pick .

                                const JustTheName = Recipe.pick({ name: true });
                                type JustTheName = z.infer<typeof JustTheName>;
                                // => { name: string }

                              To remove certain keys, use .omit .

                                const NoIDRecipe = Recipe.omit({ id: true });
                                
                                type NoIDRecipe = z.infer<typeof NoIDRecipe>;
                                // => { name: string, ingredients: string[] }

                                .partial

                              Inspired by the built-in TypeScript utility type Partial, the .partial method makes all properties optional.

                              Starting from this object:

                                const user = z.object({
                                  email: z.string(),
                                  username: z.string(),
                                });
                                // { email: string; username: string }

                              We can create a partial version:

                                const partialUser = user.partial();
                                // { email?: string | undefined; username?: string | undefined }

                              You can also specify which properties to make optional:

                                const optionalEmail = user.partial({
                                  email: true,
                                });
                                /*
                                {
                                  email?: string | undefined;
                                  username: string
                                }
                                */

                                .deepPartial

                              The .partial method is shallow — it only applies one level deep. There is also a "deep" version:

                                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}[]
                                }
                                */

                              Important limitation: deep partials only work as expected in hierarchies of objects, arrays, and tuples.

                                .required

                              Contrary to the .partial method, the .required method makes all properties required.

                              Starting from this object:

                                const user = z
                                  .object({
                                    email: z.string(),
                                    username: z.string(),
                                  })
                                  .partial();
                                // { email?: string | undefined; username?: string | undefined }

                              We can create a required version:

                                const requiredUser = user.required();
                                // { email: string; username: string }

                              You can also specify which properties to make required:

                                const requiredEmail = user.required({
                                  email: true,
                                });
                                /*
                                {
                                  email: string;
                                  username?: string | undefined;
                                }
                                */

                                .passthrough

                              By default Zod object schemas strip out unrecognized keys during parsing.

                                const person = z.object({
                                  name: z.string(),
                                });
                                
                                person.parse({
                                  name: "bob dylan",
                                  extraKey: 61,
                                });
                                // => { name: "bob dylan" }
                                // extraKey has been stripped

                              Instead, if you want to pass through unknown keys, use .passthrough() .

                                person.passthrough().parse({
                                  name: "bob dylan",
                                  extraKey: 61,
                                });
                                // => { name: "bob dylan", extraKey: 61 }

                                .strict

                              By default Zod object schemas strip out unrecognized keys during parsing. You can disallow unknown keys with .strict() . If there are any unknown keys in the input, Zod will throw an error.

                                const person = z
                                  .object({
                                    name: z.string(),
                                  })
                                  .strict();
                                
                                person.parse({
                                  name: "bob dylan",
                                  extraKey: 61,
                                });
                                // => throws ZodError

                                .strip

                              You can use the .strip method to reset an object schema to the default behavior (stripping unrecognized keys).

                                .catchall

                              You can pass a "catchall" schema into an object schema. All unknown keys will be validated against it.

                                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

                              Using .catchall() obviates .passthrough() , .strip() , or .strict(). All keys are now considered "known".

                                Arrays

                                const stringArray = z.array(z.string());
                                
                                // equivalent
                                const stringArray = z.string().array();

                              Be careful with the .array() method. It returns a new ZodArray instance. This means the order in which you call methods matters. For instance:

                                z.string().optional().array(); // (string | undefined)[]
                                z.string().array().optional(); // string[] | undefined

                                .element

                              Use .element to access the schema for an element of the array.

                                stringArray.element; // => string schema

                                .nonempty

                              If you want to ensure that an array contains at least one element, use .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

                              You can optionally specify a custom error message:

                                // 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

                              Unlike .nonempty() these methods do not change the inferred type.

                                Tuples

                              Unlike arrays, tuples have a fixed number of elements and each element can have a different type.

                                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 }]

                              A variadic ("rest") argument can be added with the .rest method.

                                const variadicTuple = z.tuple([z.string()]).rest(z.number());
                                const result = variadicTuple.parse(["hello", 1, 2, 3]);
                                // => [string, ...number[]];

                                Unions

                              Zod includes a built-in z.union method for composing "OR" types.

                                const stringOrNumber = z.union([z.string(), z.number()]);
                                
                                stringOrNumber.parse("foo"); // passes
                                stringOrNumber.parse(14); // passes

                              Zod will test the input against each of the "options" in order and return the first value that validates successfully.

                              For convenience, you can also use the .or method:

                                const stringOrNumber = z.string().or(z.number());

                              Optional string validation:

                              To validate an optional form input, you can union the desired string validation with an empty string literal.

                              This example validates an input that is optional but needs to contain a valid 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

                                Discriminated unions

                              A discriminated union is a union of object schemas that all share a particular key.

                                type MyUnion =
                                  | { status: "success"; data: string }
                                  | { status: "failed"; error: Error };

                              Such unions can be represented with the z.discriminatedUnion method. This enables faster evaluation, because Zod can check the discriminator key (status in the example above) to determine which schema should be used to parse the input. This makes parsing more efficient and lets Zod report friendlier errors.

                              With the basic union method, the input is tested against each of the provided "options", and in the case of invalidity, issues for all the "options" are shown in the zod error. On the other hand, the discriminated union allows for selecting just one of the "options", testing against it, and showing only the issues related to this "option".

                                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" });

                              You can extract a reference to the array of schemas with the .options property.

                                myUnion.options; // [ZodObject<...>, ZodObject<...>]

                              To merge two or more discriminated unions, use .options with destructuring.

                                const A = z.discriminatedUnion("status", [
                                  /* options */
                                ]);
                                const B = z.discriminatedUnion("status", [
                                  /* options */
                                ]);
                                
                                const AB = z.discriminatedUnion("status", [...A.options, ...B.options]);

                                Records

                              Record schemas are used to validate types such as Record<string, number>. This is particularly useful for storing or caching items by 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 }>

                              The schema and inferred type can be used like so:

                                const userStore: UserStore = {};
                                
                                userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
                                  name: "Carlotta",
                                }; // passes
                                
                                userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
                                  whatever: "Ice cream sundae",
                                }; // TypeError

                              A note on numerical keys

                              While z.record(keyType, valueType) is able to accept numerical key types and TypeScript's built-in Record type is Record<KeyType, ValueType>, it's hard to represent the TypeScript type Record<number, any> in Zod.

                              As it turns out, TypeScript's behavior surrounding [k: number] is a little unintuitive:

                                const testMap: { [k: number]: string } = {
                                  1: "one",
                                };
                                
                                for (const key in testMap) {
                                  console.log(`${key}: ${typeof key}`);
                                }
                                // prints: `1: string`

                              As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.

                                Maps

                                const stringNumberMap = z.map(z.string(), z.number());
                                
                                type StringNumberMap = z.infer<typeof stringNumberMap>;
                                // type StringNumberMap = Map<string, number>

                                Sets

                                const numberSet = z.set(z.number());
                                type NumberSet = z.infer<typeof numberSet>;
                                // type NumberSet = Set<number>

                              Set schemas can be further constrained with the following utility methods.

                                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

                                Intersections

                              Intersections are useful for creating "logical AND" types. This is useful for intersecting two object types.

                                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);

                              Though in many cases, it is recommended to use A.merge(B) to merge two objects. The .merge method returns a new ZodObject instance, whereas A.and(B) returns a less useful ZodIntersection instance that lacks common object methods like pick and omit.

                                const a = z.union([z.number(), z.string()]);
                                const b = z.union([z.number(), z.boolean()]);
                                const c = z.intersection(a, b);
                                
                                type c = z.infer<typeof c>; // => number

                                Recursive types

                              You can define a recursive schema in Zod, but because of a limitation of TypeScript, their type can't be statically inferred. Instead you'll need to define the type definition manually, and provide it to Zod as a "type hint".

                                const baseCategorySchema = z.object({
                                  name: z.string(),
                                });
                                
                                type Category = z.infer<typeof baseCategorySchema> & {
                                  subcategories: Category[];
                                };
                                
                                const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
                                  subcategories: z.lazy(() => categorySchema.array()),
                                });
                                
                                categorySchema.parse({
                                  name: "People",
                                  subcategories: [
                                    {
                                      name: "Politicians",
                                      subcategories: [
                                        {
                                          name: "Presidents",
                                          subcategories: [],
                                        },
                                      ],
                                    },
                                  ],
                                }); // passes

                              Thanks to crasite for this example.

                                ZodType with ZodEffects

                              When using z.ZodType with z.ZodEffects ( .refine, .transform, preprocess, etc... ), you will need to define the input and output types of the schema. 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()),
                                });

                              Thanks to marcus13371337 and JoelBeeldi for this example.

                                JSON type

                              If you want to validate any JSON value, you can use the snippet below.

                                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);

                              Thanks to ggoodman for suggesting this.

                                Cyclical objects

                              Despite supporting recursive schemas, passing cyclical data into Zod will cause an infinite loop in some cases.

                              To detect cyclical objects before they cause problems, consider this approach.

                                Promises

                                const numberPromise = z.promise(z.number());

                              "Parsing" works a little differently with promise schemas. Validation happens in two parts:

                               1. Zod synchronously checks that the input is an instance of Promise (i.e. an object with .then and .catch methods.).
                               2. Zod uses .then to attach an additional validation step onto the existing Promise. You'll have to use .catch on the returned Promise to handle validation failures.
                                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
                                };

                                Instanceof

                              You can use z.instanceof to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.

                                class Test {
                                  name: string;
                                }
                                
                                const TestSchema = z.instanceof(Test);
                                
                                const blob: any = "whatever";
                                TestSchema.parse(new Test()); // passes
                                TestSchema.parse(blob); // throws

                                Functions

                              Zod also lets you define "function schemas". This makes it easy to validate the inputs and outputs of a function without intermixing your validation code and "business logic".

                              You can create a function schema with z.function(args, returnType) .

                                const myFunction = z.function();
                                
                                type myFunction = z.infer<typeof myFunction>;
                                // => ()=>unknown

                              Define inputs and outputs.

                                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

                              Function schemas have an .implement() method which accepts a function and returns a new function that automatically validates its inputs and outputs.

                                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

                              If you only care about validating inputs, just don't call the .returns() method. The output type will be inferred from the implementation.

                              You can use the special z.void() option if your function doesn't return anything. This will let Zod properly infer the type of void-returning functions. (Void-returning functions actually return undefined.)

                                const myFunction = z
                                  .function()
                                  .args(z.string())
                                  .implement((arg) => {
                                    return [arg.length];
                                  });
                                
                                myFunction; // (arg: string)=>number[]

                              Extract the input and output schemas from a function schema.

                                myFunction.parameters();
                                // => ZodTuple<[ZodString, ZodNumber]>
                                
                                myFunction.returnType();
                                // => ZodBoolean

                                Preprocess

                              Zod now supports primitive coercion without the need for .preprocess(). See the coercion docs for more information.

                              Typically Zod operates under a "parse then transform" paradigm. Zod validates the input first, then passes it through a chain of transformation functions. (For more information about transforms, read the .transform docs.)

                              But sometimes you want to apply some transform to the input before parsing happens. A common use case: type coercion. Zod enables this with the z.preprocess().

                                const castToString = z.preprocess((val) => String(val), z.string());

                              This returns a ZodEffects instance. ZodEffects is a wrapper class that contains all logic pertaining to preprocessing, refinements, and transforms.

                                Custom schemas

                              You can create a Zod schema for any TypeScript type by using z.custom(). This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.

                                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;

                              If you don't provide a validation function, Zod will allow any value. This can be dangerous!

                                z.custom<{ arg: string }>(); // performs no validation

                              You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of .refine.

                                z.custom<...>((val) => ..., "custom error message");

                                Schema methods

                              All Zod schemas contain certain methods.

                                .parse

                              .parse(data: unknown): T

                              Given any Zod schema, you can call its .parse method to check data is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.

                              IMPORTANT: The value returned by .parse is a deep clone of the variable you passed in.

                                const stringSchema = z.string();
                                
                                stringSchema.parse("fish"); // => returns "fish"
                                stringSchema.parse(12); // throws error

                                .parseAsync

                              .parseAsync(data:unknown): Promise<T>

                              If you use asynchronous refinements or transforms (more on those later), you'll need to use .parseAsync.

                                const stringSchema = z.string().refine(async (val) => val.length <= 8);
                                
                                await stringSchema.parseAsync("hello"); // => returns "hello"
                                await stringSchema.parseAsync("hello world"); // => throws error

                                .safeParse

                              .safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }

                              If you don't want Zod to throw errors when validation fails, use .safeParse. This method returns an object containing either the successfully parsed data or a ZodError instance containing detailed information about the validation problems.

                                stringSchema.safeParse(12);
                                // => { success: false; error: ZodError }
                                
                                stringSchema.safeParse("billie");
                                // => { success: true; data: 'billie' }

                              The result is a discriminated union, so you can handle errors very conveniently:

                                const result = stringSchema.safeParse("billie");
                                if (!result.success) {
                                  // handle error then return
                                  result.error;
                                } else {
                                  // do something
                                  result.data;
                                }

                                .safeParseAsync

                              Alias: .spa

                              An asynchronous version of safeParse.

                                await stringSchema.safeParseAsync("billie");

                              For convenience, this has been aliased to .spa:

                                await stringSchema.spa("billie");

                                .refine

                              .refine(validator: (data:T)=>any, params?: RefineParams)

                              Zod lets you provide custom validation logic via refinements. (For advanced features like creating multiple issues and customizing error codes, see .superRefine.)

                              Zod was designed to mirror TypeScript as closely as possible. But there are many so-called "refinement types" you may wish to check for that can't be represented in TypeScript's type system. For instance: checking that a number is an integer or that a string is a valid email address.

                              For example, you can define a custom validation check on any Zod schema with .refine :

                                const myString = z.string().refine((val) => val.length <= 255, {
                                  message: "String can't be more than 255 characters",
                                });

                              ⚠️ Refinement functions should not throw. Instead they should return a falsy value to signal failure.

                                Arguments

                              As you can see, .refine takes two arguments.

                               1. The first is the validation function. This function takes one input (of type T — the inferred type of the schema) and returns any. Any truthy value will pass validation. (Prior to zod@1.6.2 the validation function had to return a boolean.)
                               2. The second argument accepts some options. You can use this to customize certain error-handling behavior:
                                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;
                                };

                              For advanced cases, the second argument can also be a function that returns RefineParams.

                                const longString = z.string().refine(
                                  (val) => val.length > 10,
                                  (val) => ({ message: `${val} is not more than 10 characters` })
                                );

                                Customize error path

                                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" });

                              Because you provided a path parameter, the resulting error will be:

                                ZodError {
                                  issues: [{
                                    "code": "custom",
                                    "path": [ "confirm" ],
                                    "message": "Passwords don't match"
                                  }]
                                }

                                Asynchronous refinements

                              Refinements can also be async:

                                const userId = z.string().refine(async (id) => {
                                  // verify that ID exists in database
                                  return true;
                                });

                              ⚠️ If you use async refinements, you must use the .parseAsync method to parse data! Otherwise Zod will throw an error.

                                Relationship to transforms

                              Transforms and refinements can be interleaved:

                                z.string()
                                  .transform((val) => val.length)
                                  .refine((val) => val > 25);

                                .superRefine

                              The .refine method is actually syntactic sugar atop a more versatile (and verbose) method called superRefine. Here's an example:

                                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.`,
                                    });
                                  }
                                });

                              You can add as many issues as you like. If ctx.addIssue is not called during the execution of the function, validation passes.

                              Normally refinements always create issues with a ZodIssueCode.custom error code, but with superRefine it's possible to throw issues of any ZodIssueCode. Each issue code is described in detail in the Error Handling guide: ERROR_HANDLING.md.

                                Abort early

                              By default, parsing will continue even after a refinement check fails. For instance, if you chain together multiple refinements, they will all be executed. However, it may be desirable to abort early to prevent later refinements from being executed. To achieve this, pass the fatal flag to ctx.addIssue and return 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",
                                    });
                                  }
                                });

                                Type refinements

                              If you provide a type predicate to .refine() or .superRefine(), the resulting type will be narrowed down to your predicate's type. This is useful if you are mixing multiple chained refinements and transformations:

                                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`!");

                              ⚠️ You must use ctx.addIssue() instead of returning a boolean value to indicate whether the validation passes. If ctx.addIssue is not called during the execution of the function, validation passes.

                                .transform

                              To transform data after parsing, use the transform method.

                                const stringToNumber = z.string().transform((val) => val.length);
                                
                                stringToNumber.parse("string"); // => 6

                                Chaining order

                              Note that stringToNumber above is an instance of the ZodEffects subclass. It is NOT an instance of ZodString. If you want to use the built-in methods of ZodString (e.g. .email()) you must apply those methods before any transforms.

                                const emailToDomain = z
                                  .string()
                                  .email()
                                  .transform((val) => val.split("@")[1]);
                                
                                emailToDomain.parse("colinhacks@example.com"); // => example.com

                                Validating during transform

                              The .transform method can simultaneously validate and transform the value. This is often simpler and less duplicative than chaining transform and refine.

                              As with .superRefine, the transform function receives a ctx object with an addIssue method that can be used to register validation issues.

                                const numberInString = z.string().transform((val, ctx) => {
                                  const parsed = parseInt(val);
                                  if (isNaN(parsed)) {
                                    ctx.addIssue({
                                      code: z.ZodIssueCode.custom,
                                      message: "Not a number",
                                    });
                                
                                    // This is a special symbol you can use to
                                    // return early from the transform function.
                                    // It has type `never` so it does not affect the
                                    // inferred return type.
                                    return z.NEVER;
                                  }
                                  return parsed;
                                });

                                Relationship to refinements

                              Transforms and refinements can be interleaved. These will be executed in the order they are declared.

                                const nameToGreeting = z
                                  .string()
                                  .transform((val) => val.toUpperCase())
                                  .refine((val) => val.length > 15)
                                  .transform((val) => `Hello ${val}`)
                                  .refine((val) => val.indexOf("!") === -1);

                                Async transforms

                              Transforms can also be async.

                                const IdToUser = z
                                  .string()
                                  .uuid()
                                  .transform(async (id) => {
                                    return await getUserById(id);
                                  });

                              ⚠️ If your schema contains asynchronous transforms, you must use .parseAsync() or .safeParseAsync() to parse data. Otherwise Zod will throw an error.

                                .default

                              You can use transforms to implement the concept of "default values" in Zod.

                                const stringWithDefault = z.string().default("tuna");
                                
                                stringWithDefault.parse(undefined); // => "tuna"

                              Optionally, you can pass a function into .default that will be re-executed whenever a default value needs to be generated:

                                const numberWithRandomDefault = z.number().default(Math.random);
                                
                                numberWithRandomDefault.parse(undefined); // => 0.4413456736055323
                                numberWithRandomDefault.parse(undefined); // => 0.1871840107401901
                                numberWithRandomDefault.parse(undefined); // => 0.7223408162401552

                              Conceptually, this is how Zod processes default values:

                               1. If the input is undefined, the default value is returned
                               2. Otherwise, the data is parsed using the base schema

                                .describe

                              Use .describe() to add a description property to the resulting schema.

                                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…

                              This can be useful for documenting a field, for example in a JSON Schema using a library like zod-to-json-schema).

                                .catch

                              Use .catch() to provide a "catch value" to be returned in the event of a parsing error.

                                const numberWithCatch = z.number().catch(42);
                                
                                numberWithCatch.parse(5); // => 5
                                numberWithCatch.parse("tuna"); // => 42

                              Optionally, you can pass a function into .catch that will be re-executed whenever a default value needs to be generated. A ctx object containing the caught error will be passed into this function.

                                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

                              Conceptually, this is how Zod processes "catch values":

                               1. The data is parsed using the base schema
                               2. If the parsing fails, the "catch value" is returned

                                .optional

                              A convenience method that returns an optional version of a schema.

                                const optionalString = z.string().optional(); // string | undefined
                                
                                // equivalent to
                                z.optional(z.string());

                                .nullable

                              A convenience method that returns a nullable version of a schema.

                                const nullableString = z.string().nullable(); // string | null
                                
                                // equivalent to
                                z.nullable(z.string());

                                .nullish

                              A convenience method that returns a "nullish" version of a schema. Nullish schemas will accept both undefined and null. Read more about the concept of "nullish" in the TypeScript 3.7 release notes.

                                const nullishString = z.string().nullish(); // string | null | undefined
                                
                                // equivalent to
                                z.string().nullable().optional();

                                .array

                              A convenience method that returns an array schema for the given type:

                                const stringArray = z.string().array(); // string[]
                                
                                // equivalent to
                                z.array(z.string());

                                .promise

                              A convenience method for promise types:

                                const stringPromise = z.string().promise(); // Promise<string>
                                
                                // equivalent to
                                z.promise(z.string());

                                .or

                              A convenience method for union types.

                                const stringOrNumber = z.string().or(z.number()); // string | number
                                
                                // equivalent to
                                z.union([z.string(), z.number()]);

                                .and

                              A convenience method for creating intersection types.

                                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's type system is structural, which means that any two types that are structurally equivalent are considered the same.

                                type Cat = { name: string };
                                type Dog = { name: string };
                                
                                const petCat = (cat: Cat) => {};
                                const fido: Dog = { name: "fido" };
                                petCat(fido); // works fine

                              In some cases, its can be desirable to simulate nominal typing inside TypeScript. For instance, you may wish to write a function that only accepts an input that has been validated by Zod. This can be achieved with branded types (AKA opaque types).

                                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" });

                              Under the hood, this works by attaching a "brand" to the inferred type using an intersection type. This way, plain/unbranded data structures are no longer assignable to the inferred type of the schema.

                                const Cat = z.object({ name: z.string() }).brand<"Cat">();
                                type Cat = z.infer<typeof Cat>;
                                // {name: string} & {[symbol]: "Cat"}

                              Note that branded types do not affect the runtime result of .parse. It is a static-only construct.

                                .readonly

                              .readonly() => ZodReadonly<this>

                              This method returns a ZodReadonly schema instance that parses the input using the base schema, then calls Object.freeze() on the result. The inferred type is also marked as 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

                              The inferred type uses TypeScript's built-in readonly types when relevant.

                                z.array(z.string()).readonly();
                                // readonly string[]
                                
                                z.tuple([z.string(), z.number()]).readonly();
                                // readonly [string, number]
                                
                                z.map(z.string(), z.date()).readonly();
                                // ReadonlyMap<string, Date>
                                
                                z.set(z.string()).readonly();
                                // ReadonlySet<string>

                                .pipe

                              Schemas can be chained into validation "pipelines". It's useful for easily validating the result after a .transform():

                                z.string()
                                  .transform((val) => val.length)
                                  .pipe(z.number().min(5));

                              The .pipe() method returns a ZodPipeline instance.

                                You can use .pipe() to fix common issues with z.coerce.

                              You can constrain the input to types that work well with your chosen coercion. Then use .pipe() to apply the coercion.

                              without constrained input:

                                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

                              with constrained input:

                                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

                              You can also use this technique to avoid coercions that throw uncaught errors.

                              without constrained input:

                                const toBigInt = z.coerce.bigint();
                                
                                // works intuitively
                                console.log(toBigInt.safeParse("42")); // true
                                
                                // probably not what you want
                                console.log(toBigInt.safeParse(null)); // throws uncaught error

                              with constrained input:

                                const toNumber = z.number().or(z.string()).pipe(z.coerce.number());
                                const toBigInt = z.bigint().or(toNumber).pipe(z.coerce.bigint());
                                
                                // still works intuitively
                                console.log(toBigInt.safeParse("42").success); // true
                                
                                // error handled by zod, more likely what you want
                                console.log(toBigInt.safeParse(null).success); // false

                                Guides and concepts

                                Type inference

                              You can extract the TypeScript type of any schema with z.infer<typeof mySchema> .

                                const A = z.string();
                                type A = z.infer<typeof A>; // string
                                
                                const u: A = 12; // TypeError
                                const u: A = "asdf"; // compiles

                              What about transforms?

                              In reality each Zod schema internally tracks two types: an input and an output. For most schemas (e.g. z.string()) these two are the same. But once you add transforms into the mix, these two values can diverge. For instance z.string().transform(val => val.length) has an input of string and an output of number.

                              You can separately extract the input and output types like 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

                                Writing generic functions

                              With TypeScript generics, you can write reusable functions that accept Zod schemas as parameters. This enables you to create custom validation logic, schema transformations, and more, while maintaining type safety and inference.

                              When attempting to write a function that accepts a Zod schema as an input, it's tempting to try something like this:

                                function inferSchema<T>(schema: z.ZodType<T>) {
                                  return schema;
                                }

                              This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of schema will be an instance of ZodType.

                                inferSchema(z.string());
                                // => ZodType<string>

                              This approach loses type information, namely which subclass the input actually is (in this case, ZodString). That means you can't call any string-specific methods like .min() on the result of inferSchema.

                              A better approach is to infer the schema as a whole instead of merely its inferred type. You can do this with a utility type called z.ZodTypeAny.

                                function inferSchema<T extends z.ZodTypeAny>(schema: T) {
                                  return schema;
                                }
                                
                                inferSchema(z.string());
                                // => ZodString

                              ZodTypeAny is just a shorthand for ZodType<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.

                                Inferring the inferred type

                              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

                                Constraining allowable inputs

                              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>'

                                Error handling

                              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

                                Error formatting

                              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"]
                                }

                                Comparison

                              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.

                                Joi

                              https://github.com/hapijs/joi

                              Doesn't support static type inference 😕

                                Yup

                              https://github.com/jquense/yup

                              Yup is a full-featured library that was implemented first in vanilla JS, and later rewritten in TypeScript.

                                * Supports casting and transforms
                                * All object fields are optional by default
                                * Missing promise schemas
                                * Missing function schemas
                                * Missing union & intersection schemas

                                io-ts

                              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.

                                * Supports codecs with serialization & deserialization transforms
                                * Supports branded types
                                * Supports advanced functional programming, higher-kinded types, fp-ts compatibility
                                * Missing object methods: (pick, omit, partial, deepPartial, merge, extend)
                                * Missing nonempty arrays with proper typing ([T, ...T[]])
                                * Missing promise schemas
                                * Missing function schemas

                                Runtypes

                              https://github.com/pelotom/runtypes

                              Good type inference support.

                                * Supports "pattern matching": computed properties that distribute over unions
                                * Missing object methods: (deepPartial, merge)
                                * Missing nonempty arrays with proper typing ([T, ...T[]])
                                * Missing promise schemas
                                * Missing error customization

                                Ow

                              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 (e.g. 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.

                                Changelog

                              View the changelog at CHANGELOG.md

                          About

                          TypeScript-first schema validation with static type inference

                            zod.dev

                          Topics

                              typescript static-types schema-validation type-inference runtime-validation

                          Resources

                            Readme

                          License

                            MIT license

                          Code of conduct

                            Code of conduct
                            Activity

                          Stars

                            32.5k stars

                          Watchers

                            62 watching

                          Forks

                            1.1k forks
                            Report repository

                        Releases 89

                            v3.23.8 Latest
                            May 8, 2024
                          + 88 releases

                        Sponsor this project

                        Sponsor
                          Learn more about GitHub Sponsors

                        Packages 0

                          No packages published

                        Used by 1.2m

                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                        + 1,248,725

                        Contributors 300

                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          * 
                          + 286 contributors

                        Languages

                          * TypeScript 96.2%
                          * JavaScript 1.9%
                          * HTML 1.9%

    Footer

        © 2024 GitHub, Inc.

      Footer navigation

        * Terms
        * Privacy
        * Security
        * Status
        * Docs
        * Contact
        * Manage cookies
        * Do not share my personal information
      You can’t perform that action at this time.
GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference
https://github.com/colinhacks/zod
pksilen
2021-09-08T16:36:15Z
<div><div><article><p></p><h2>validated-types</h2><a href="#validated-types"></a><p></p>
<p><code>validated-types</code> is a library for Typescript to create types for validated integer, float, string and array values.
It also allows of creating semantic types and declare variables with semantic types.</p>
<p><a href="https://www.npmjs.com/package/validated-types"></a>
<a href="https://circleci.com/gh/pksilen/validated-types/tree/main"></a>
<a href="https://codecov.io/gh/pksilen/validated-types"></a>
<a href="https://sonarcloud.io/dashboard?id=pksilen_validated-types"></a>
<a href="https://sonarcloud.io/dashboard?id=pksilen_validated-types"></a>
<a href="https://sonarcloud.io/dashboard?id=pksilen_validated-types"></a>
<a href="https://www.npmjs.com/package/validated-types"></a>
<a href="https://github.com/pksilen/validated-types/blob/master/LICENSE"></a></p>
<p></p><h2>Table of Contents</h2><a href="#table-of-contents"></a><p></p>
<ul>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#usage">Usage</a>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#validated-integers">Validate Integers</a></li>
<li><a href="#validated-floats">Validate Floats</a></li>
<li><a href="#validated-strings">Validate Strings</a></li>
<li><a href="#validated-arrays">Validate Arrays</a></li>
<li><a href="#validated-objects">Validate Objects</a></li>
<li><a href="#create-semantic-types">Create Semantic Types/Variables</a></li>
<li><a href="#create-semantic-validated-integers">Create Semantic Validated Integers</a></li>
<li><a href="#create-semantic-validated-floats">Create Semantic Validated Floats</a></li>
<li><a href="#create-semantic-validated-strings">Create Semantic Validated Strings</a></li>
</ul>
</li>
<li><a href="#api-documentation">API Documentation</a>
<ul>
<li><a href="#vfloat">VFloat</a>
<ul>
<li><a href="#vfloat-registerCustomValidator">registerCustomValidator</a></li>
<li><a href="#vfloat-createOrThrow">createOrThrow</a></li>
<li><a href="#vfloat-create">create</a></li>
<li><a href="#vfloat-createOrError">createOrError</a></li>
<li><a href="#vfloat-value">value</a></li>
</ul>
</li>
<li><a href="#vint">VInt</a>
<ul>
<li><a href="#vint-registerCustomValidator">registerCustomValidator</a></li>
<li><a href="#vint-createOrThrow">createOrThrow</a></li>
<li><a href="#vint-create">create</a></li>
<li><a href="#vint-createOrError">createOrError</a></li>
<li><a href="#vint-value">value</a></li>
</ul>
</li>
<li><a href="#vstring">VString</a>
<ul>
<li><a href="#vstring-registerCustomValidator">registerCustomValidator</a></li>
<li><a href="#vstring-createOrThrow">createOrThrow</a></li>
<li><a href="#vstring-create">create</a></li>
<li><a href="#vstring-createOrError">createOrError</a></li>
<li><a href="#vstring-value">value</a></li>
</ul>
</li>
<li><a href="#varray">VArray</a>
<ul>
<li><a href="#varray-registerCustomValidator">registerCustomValidator</a></li>
<li><a href="#varray-createOrThrow">createOrThrow</a></li>
<li><a href="#varray-create">create</a></li>
<li><a href="#varray-createOrError">createOrError</a></li>
<li><a href="#varray-value">value</a></li>
</ul>
</li>
<li><a href="#SemType">SemType</a>
<ul>
<li><a href="#SemType-constructor">constructor</a></li>
<li><a href="#SemType-value">value</a></li>
</ul>
</li>
<li><a href="#SemVInt">SemVInt</a></li>
<li><a href="#SemVFloat">SemVFloat</a></li>
<li><a href="#SemVString">SemVString</a></li>
<li><a href="#vspecof">VSpecOf</a></li>
</ul>
</li>
<li><a href="#feedback">Feedback</a></li>
<li><a href="#license">License</a></li>
</ul>
<p></p><h2><a></a> Prerequisites</h2><a href="#-prerequisites"></a><p></p>
<ul>
<li>Typescript &gt;= 4.1.0</li>
</ul>
<p></p><h2><a></a> Installation</h2><a href="#-installation"></a><p></p>
<div><pre>npm install --save validated-types</pre></div>
<p></p><h2><a></a> Usage</h2><a href="#-usage"></a><p></p>
<p></p><h3><a></a> Introduction</h3><a href="#-introduction"></a><p></p>
<p>Validated-types is a type value validation library for Typescript. You can validate values of integers, floats, strings and arrays.
For numbers, you can for example validate the minimum and maximum value. For strings, you can validate the length and also perform semantic validation
to validate if a string should be, for example, a valid URL, IP address or email address.</p>
<p>By using validated types for the parameters of your application's functions, you can rest assured that only proper values are ever passed to your function.
You don't have to do any validation work inside your functions, just use the value of already validated parameter. The validation of the value is done only once upon the construction of validated objects,
so there is no performance penalty in using the validated values as many times as you need.</p>
<p>You should create the validated integer, float, string and array objects in functions that receive unvalidated input data and then pass the validated values to the rest of the functions in your application.</p>
<p>Your application typically receives unvalidated input data from external sources in following scenarios:</p>
<ul>
<li>Reading command line arguments</li>
<li>Reading environment variables</li>
<li>Reading standard input</li>
<li>Reading file(s) from file system</li>
<li>Reading data from socket (network input)</li>
<li>End-user input from user interface</li>
</ul>
<p>You can also create semantic types and semantically typed variables using <code>SemType</code>. Using semantic types, you
can differentiate between multiple types of the same basic type. For example, If a function accepts two boolean arguments, it is possible
that the calling function gives those two arguments in wrong order, but you never notice it, because it does not generate a compilation error.
Using semantic types, you can differentiate between those two boolean types by giving them two different semantic names.
Semantic name is just any string describing the purpose of type/variable.</p>
<p>The library contains static factory methods in the classes forr creating a new instance of the specific class.
There are different factory methods available. You can choose which factory method to use depending on your
application need. The factory methods are following:</p>
<ul>
<li><code>tryCreate(...)</code> creates a validated value object or throws an exception</li>
<li><code>createOrThrow(...)</code> is same as above, i.e. creates a validated value object or throws an exception</li>
<li><code>create(...)</code> creates a validated value object or returns <code>null</code>. Use this method if you don't need the error reason</li>
<li><code>createOrError(...)</code> creates a validated value object or returns an error object, always returns a pair (is similar to Golang returning an error)</li>
</ul>
<p></p><h3><a></a> Validate Integers</h3><a href="#-validate-integers"></a><p></p>
<p>You can validate your integer, float and string type variables with <code>validated-types</code>.
For example, to create a validated integer which allows values between 1 and 10, you declare:</p>
<div><pre><span>import</span> <span>{</span> <span>VInt</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>function</span> <span>useInt</span><span>(</span><span>int</span>: <span>VInt</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>// use int here</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>int</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>int</span> <span>=</span> <span>VInt</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>5</span><span>)</span><span>;</span>
<span>const</span> <span>maybeInt</span> <span>=</span> <span>VInt</span><span>.</span><span>create</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>12</span><span>)</span><span>;</span> <span>// Returns null</span>

<span>useInt</span><span>(</span><span>int</span><span>)</span><span>;</span> <span>// prints to console: 5</span>
<span>useInt</span><span>(</span><span>maybeInt</span> <span>??</span> <span>VInt</span><span>.</span><span>tryCreate</span><span>(</span><span>'1,10'</span><span>,</span> <span>10</span><span>)</span><span>)</span><span>;</span> <span>// prints to console: 10</span></pre></div>
<p>You can also register a custom validator:</p>
<div><pre><span>import</span> <span>{</span> <span>VInt</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>VInt</span><span>.</span><span>registerCustomValidator</span><span>(</span><span>'isEven'</span><span>,</span> <span>(</span><span>value</span><span>)</span> <span>=&gt;</span> <span>value</span> <span>%</span> <span>2</span> <span>===</span> <span>0</span><span>)</span><span>;</span>

<span>const</span> <span>evenNumber</span> <span>=</span> <span>VInt</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'custom:isEven'</span><span>&gt;</span><span>(</span><span>'custom:isEven'</span><span>,</span> <span>2</span><span>)</span><span>;</span>
<span>const</span> <span>maybeEvenNumber</span> <span>=</span> <span>VInt</span><span>&lt;</span><span>'custom:isEven'</span><span>&gt;</span><span>.</span><span>create</span><span>(</span><span>'custom:isEven'</span><span>,</span> <span>1</span><span>)</span><span>;</span></pre></div>
<p>Custom validator must be registered before it is used by any validated types <code>create</code>, <code>createOrThrow</code> or <code>createOrError</code>method.
This means that you should register your custom validators as early as possible in your application code.
If custom validator is not registered, and it is used, an exception will be thrown.</p>
<p></p><h3><a></a> Validate Floats</h3><a href="#-validate-floats"></a><p></p>
<p>To create a validated float which allows positive values only, you declare:</p>
<div><pre><span>import</span> <span>{</span> <span>VFloat</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>function</span> <span>useFloat</span><span>(</span><span>float</span>: <span>VFloat</span><span>&lt;</span><span>'positive'</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>// use float here</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>float</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>float</span> <span>=</span> <span>VFloat</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'positive'</span><span>&gt;</span><span>(</span><span>'positive'</span><span>,</span> <span>5.25</span><span>)</span><span>;</span>
<span>const</span> <span>maybeFloat</span> <span>=</span> <span>VFloat</span><span>&lt;</span><span>'positive'</span><span>&gt;</span><span>.</span><span>create</span><span>(</span><span>'positive'</span><span>,</span> <span>-</span><span>5.25</span><span>)</span><span>;</span> <span>// returns null</span>

<span>useFloat</span><span>(</span><span>float</span><span>)</span><span>;</span> <span>// prints to console: 5.25</span>
<span>useFloat</span><span>(</span><span>maybeFloat</span> <span>??</span> <span>VFloat</span><span>.</span><span>tryCreate</span><span>(</span><span>'positive'</span><span>,</span> <span>1</span><span>)</span><span>)</span><span>;</span> <span>// prints to console: 1</span></pre></div>
<p></p><h3><a></a> Validate Strings</h3><a href="#-validate-strings"></a><p></p>
<p>To create a validated string which allows URLs with minimum length of one and maximum length of 1024 characters, you declare:</p>
<div><pre><span>import</span> <span>{</span> <span>VString</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>function</span> <span>useUrl</span><span>(</span><span>url</span>: <span>VString</span><span>&lt;</span><span>'1,1024,url'</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>// use URL here</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>url</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>url</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'1,1024,url'</span><span>&gt;</span><span>(</span><span>'1,1024,url'</span><span>,</span> <span>'https://www.mydomain.com'</span><span>)</span><span>;</span>
<span>const</span> <span>maybeUrl</span> <span>=</span> <span>VString</span><span>&lt;</span><span>'1,1024,url'</span><span>&gt;</span><span>.</span><span>create</span><span>(</span><span>'1,1024,url'</span><span>,</span> <span>'invalid URL'</span><span>)</span><span>;</span> <span>// Returns null</span>

<span>useUrl</span><span>(</span><span>url</span><span>)</span><span>;</span> <span>// prints to console: https://www.mydomain.com</span>
<span>useUrl</span><span>(</span><span>maybeUrl</span> <span>??</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>'1,1024,url'</span><span>,</span> <span>'https://google.com'</span><span>)</span><span>)</span><span>;</span> <span>// prints to console: https://google.com</span></pre></div>
<p>You can combine up to 5 different string validators together. Multiple validators are given as a tuple which can have 2-5 elements. The first element of the tuple should validate the length of the string, if needed. Rest of the elements in tuple should not validate the length of string anymore.
Below example contains 4 validators that validate following string:</p>
<ul>
<li>is at least 1 characters long</li>
<li>is at most 1024 characters long</li>
<li>is lower case string</li>
<li>is valid URL</li>
<li>URL starts with <em>https</em></li>
<li>URL ends with <em>.html</em></li>
</ul>
<div><pre><span>import</span> <span>{</span> <span>SpecOf</span><span>,</span> <span>VString</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>Url</span> <span>=</span> <span>VString</span><span>&lt;</span><span>[</span><span>'1,1024,lowercase'</span><span>,</span> <span>'url'</span><span>,</span> <span>'startsWith,https'</span><span>,</span> <span>'endsWith,.html'</span><span>]</span><span>&gt;</span><span>;</span>
<span>const</span> <span>urlVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Url</span><span>&gt;</span> <span>=</span> <span>[</span><span>'1,1024,lowercase'</span><span>,</span> <span>'url'</span><span>,</span> <span>'startsWith,https'</span><span>,</span> <span>'endsWith,.html'</span><span>]</span><span>;</span>

<span>function</span> <span>useUrl</span><span>(</span><span>url</span>: <span>Url</span><span>)</span> <span>{</span>
  <span>// use URL here</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>url</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>url</span>: <span>Url</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>urlVSpec</span><span>,</span> <span>'https://server.domain.com:8080/index.html'</span><span>)</span><span>;</span>
<span>const</span> <span>maybeUrl</span>: <span>Url</span> <span>|</span> <span>null</span> <span>=</span> <span>VString</span><span>.</span><span>create</span><span>(</span><span>urlVSpec</span><span>,</span> <span>'invalid URL'</span><span>)</span><span>;</span> <span>// Returns null</span>

<span>useUrl</span><span>(</span><span>url</span><span>)</span><span>;</span> <span>// prints to console: https://server.domain.com:8080/index.html</span>
<span>useUrl</span><span>(</span><span>maybeUrl</span> <span>??</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>urlVSpec</span><span>,</span> <span>'https://server.domain.com:8080/index.html'</span><span>)</span><span>)</span><span>;</span> <span>// prints to console: https://server.domain.com:8080/index.html</span></pre></div>
<p></p><h3><a></a> Validate Arrays</h3><a href="#-validate-arrays"></a><p></p>
<p>To create a validated array of numbers which allows array length to be from 0 to 10 and requires all array elements to be unique, you declare:</p>
<div><pre><span>import</span> <span>{</span> <span>VArray</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>function</span> <span>useArray</span><span>(</span><span>array</span>: <span>VArray</span><span>&lt;</span><span>'0,10,unique'</span><span>,</span> <span>number</span><span>&gt;</span><span>)</span> <span>{</span>
  <span>// use array here</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>array</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>array</span> <span>=</span> <span>VArray</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'0,10,unique'</span><span>,</span> <span>number</span><span>&gt;</span><span>(</span><span>'0,10,unique'</span><span>,</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>]</span><span>)</span><span>;</span>
<span>const</span> <span>maybeArray</span> <span>=</span> <span>VArray</span><span>&lt;</span><span>'0,10,unique'</span><span>,</span> <span>number</span><span>&gt;</span><span>.</span><span>create</span><span>(</span><span>'0,10,unique'</span><span>,</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>2</span><span>]</span><span>)</span><span>;</span>

<span>useArray</span><span>(</span><span>array</span><span>)</span><span>;</span> <span>// prints to console: [1, 2, 3]</span>
<span>useArray</span><span>(</span><span>maybeArray</span> <span>??</span> <span>VArray</span><span>.</span><span>tryCreate</span><span>(</span><span>'0,10,unique'</span><span>,</span> <span>[</span><span>3</span><span>,</span> <span>4</span><span>,</span> <span>5</span><span>]</span><span>)</span><span>)</span><span>;</span> <span>// prints to console: [3, 4, 5]</span></pre></div>
<p>You can also create an array of validated objects, for example below example validates an array of from 1 to max 10 unique email addresses:</p>
<div><pre><span>import</span> <span>{</span> <span>VArray</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>EmailAddresses</span> <span>=</span>  <span>VArray</span><span>&lt;</span><span>'1,10,unique'</span><span>,</span> <span>VString</span><span>&lt;</span><span>'email'</span><span>&gt;</span><span>&gt;</span><span>;</span>
<span>const</span> <span>emailAddressesVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>EmailAddresses</span><span>&gt;</span> <span>=</span> <span>'1,10,unique'</span><span>;</span>

<span>function</span> <span>sendEmails</span><span>(</span><span>emailAddresses</span>: <span>EmailAddresses</span><span>,</span> <span>subject</span>: <span>string</span><span>,</span> <span>body</span>: <span>string</span><span>)</span> <span>{</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>emailAddresses</span><span>.</span><span>forEach</span><span>(</span><span>emailAddress</span><span>=&gt;</span> <span>emailAddress</span><span>.</span><span>value</span><span>)</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>emailAddress</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'email'</span><span>&gt;</span><span>(</span><span>'email'</span><span>,</span> <span>'test@example.com'</span><span>)</span><span>;</span>
<span>const</span> <span>emailAddress2</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>&lt;</span><span>'email'</span><span>&gt;</span><span>(</span><span>'email'</span><span>,</span> <span>'test2@example.com'</span><span>)</span><span>;</span>
<span>const</span> <span>emailAddresses</span>: <span>EmailAddresses</span> <span>=</span> <span>VArray</span><span>.</span><span>tryCreate</span><span>(</span><span>emailAddressesVSpec</span><span>,</span> <span>[</span><span>emailAddress</span><span>,</span> <span>emailAddress2</span><span>]</span><span>)</span><span>;</span>

<span>sendEmails</span><span>(</span><span>emailAddresses</span><span>,</span> <span>'subj'</span><span>,</span> <span>'body'</span><span>)</span><span>;</span> <span>// prints to console: 'test@example.com' and 'test2@example.com'</span></pre></div>
<p></p><h3><a></a> Validate Objects</h3><a href="#-validate-objects"></a><p></p>
<p>You can also create validated objects, for example:</p>
<div><pre><span>type</span> <span>Person</span> <span>=</span> <span>{</span>
  <span>firstName</span>: <span>VString</span><span>&lt;</span><span>1</span><span>,</span> <span>64</span><span>&gt;</span><span>;</span>
  <span>lastName</span>: <span>VString</span><span>&lt;</span><span>1</span><span>,</span> <span>64</span><span>&gt;</span><span>;</span>
  <span>nickNames</span>: <span>VString</span><span>&lt;</span><span>1</span><span>,</span> <span>64</span><span>&gt;</span><span>[</span><span>]</span><span>;</span>
  <span>email</span>: <span>VString</span><span>&lt;</span><span>'email'</span><span>&gt;</span><span>;</span>
  <span>password</span>: <span>VString</span><span>&lt;</span><span>'8,1024,strongPassword'</span><span>&gt;</span><span>;</span>
  <span>age</span>: <span>VInt</span><span>&lt;</span><span>0</span><span>,</span> <span>255</span><span>&gt;</span><span>;</span>
  <span>interestPercent</span>: <span>VFloat</span><span>&lt;</span><span>'0,100'</span><span>&gt;</span><span>;</span>
<span>}</span><span>;</span></pre></div>
<p>You can assign type aliases to your validated types:</p>
<p>types.ts</p>
<div><pre><span>import</span> <span>{</span> <span>VFloat</span><span>,</span> <span>VInt</span><span>,</span> <span>VString</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>export</span> <span>type</span> <span>Name</span> <span>=</span> <span>VString</span><span>&lt;</span><span>1</span><span>,</span> <span>64</span><span>&gt;</span><span>;</span>
<span>export</span> <span>type</span> <span>Email</span> <span>=</span> <span>VString</span><span>&lt;</span><span>'email'</span><span>&gt;</span><span>;</span>
<span>export</span> <span>type</span> <span>Password</span> <span>=</span> <span>VString</span><span>&lt;</span><span>'8,1024,strongPassword'</span><span>&gt;</span><span>;</span>
<span>export</span> <span>type</span> <span>Age</span> <span>=</span> <span>VInt</span><span>&lt;</span><span>0</span><span>,</span> <span>255</span><span>&gt;</span><span>;</span>
<span>export</span> <span>type</span> <span>Percent</span> <span>=</span> <span>VFloat</span><span>&lt;</span><span>'0,100'</span><span>&gt;</span><span>;</span></pre></div>
<p>person.ts</p>
<div><pre><span>import</span> <span>{</span> <span>Age</span><span>,</span> <span>Email</span><span>,</span> <span>Name</span><span>,</span> <span>Password</span><span>,</span> <span>Percent</span> <span>}</span> <span>from</span> <span>'types'</span><span>;</span>

<span>type</span> <span>Person</span> <span>=</span> <span>{</span>
  <span>firstName</span>: <span>Name</span><span>;</span>
  <span>lastName</span>: <span>Name</span><span>;</span>
  <span>nickNames</span>: <span>Name</span><span>[</span><span>]</span><span>;</span>
  <span>email</span>: <span>Email</span><span>;</span>
  <span>password</span>: <span>Password</span><span>;</span>
  <span>age</span>: <span>Age</span><span>;</span>
  <span>interestPercent</span>: <span>Percent</span><span>;</span>
<span>}</span><span>;</span></pre></div>
<p></p><h3><a></a> Create Semantic Types/Variables</h3><a href="#-create-semantic-typesvariables"></a><p></p>
<p>Semantic types and variables let you differentiate between variables of same type. The differentiation is done
by assigning a semantic name to the type. Following example declares two semantic variables of <code>boolean</code> type with two different semantic names.</p>
<div><pre><span>import</span> <span>{</span> <span>SemType</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>IsRecursiveCall</span> <span>=</span> <span>SemType</span><span>&lt;</span><span>boolean</span><span>,</span> <span>'isRecursiveCall'</span><span>&gt;</span>
<span>type</span> <span>IsInternalCall</span> <span>=</span> <span>SemType</span><span>&lt;</span><span>boolean</span><span>,</span> <span>'isInternalCall'</span><span>&gt;</span><span>;</span>

<span>function</span> <span>myFunc</span><span>(</span><span>isRecursiveCall</span>: <span>IsRecursiveCall</span><span>,</span> <span>isInternalCall</span>: <span>IsInternalCall</span><span>)</span> <span>{</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>isRecursiveCall</span><span>.</span><span>value</span><span>)</span><span>;</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>isInternalCall</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>isRecursiveCall</span> <span>=</span> <span>false</span><span>;</span>
<span>const</span> <span>isInternalCall</span> <span>=</span> <span>true</span><span>;</span>

<span>// Only this will succeed</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>{</span> isRecursiveCall <span>}</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>{</span> isInternalCall <span>}</span><span>)</span><span>)</span><span>;</span>

<span>// These will fail during compilation</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>{</span> isInternalCall <span>}</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>{</span> isRecursiveCall <span>}</span><span>)</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>true</span><span>,</span> <span>true</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>'isSomethingElse'</span><span>,</span> <span>true</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>'isInternalCall'</span><span>,</span> <span>true</span><span>)</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>'isRecursiveCall'</span><span>,</span> <span>false</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>'isSomethingElse'</span><span>,</span> <span>true</span><span>)</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>'isSomethingElse'</span><span>,</span> <span>true</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>'isSomethingElse'</span><span>,</span> <span>true</span><span>)</span><span>)</span><span>;</span></pre></div>
<p>You can use a validated type as a semantic type also. In the below example, a function takes two semantic parameters
which both have the same base type <code>VString&lt;'1,64'&gt;</code>.</p>
<div><pre><span>import</span> <span>{</span> <span>SemType</span><span>,</span> <span>VString</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>Name</span> <span>=</span> <span>VString</span><span>&lt;</span><span>'1,64'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>nameVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Name</span><span>&gt;</span> <span>=</span> <span>'1,64'</span><span>;</span>
<span>type</span> <span>FirstName</span> <span>=</span> <span>SemType</span><span>&lt;</span><span>Name</span><span>,</span> <span>'firstName'</span><span>&gt;</span><span>;</span>
<span>type</span> <span>LastName</span> <span>=</span> <span>SemType</span><span>&lt;</span><span>Name</span><span>,</span> <span>'lastName'</span><span>&gt;</span><span>;</span>

<span>function</span> <span>myFunc</span><span>(</span><span>firstName</span>: <span>FirstName</span><span>,</span> <span>lastName</span>: <span>LastName</span><span>)</span> <span>{</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>firstName</span><span>.</span><span>value</span><span>)</span><span>;</span>
  <span>console</span><span>.</span><span>log</span><span>(</span><span>lastName</span><span>.</span><span>value</span><span>)</span><span>;</span>
<span>}</span>

<span>const</span> <span>firstName</span>: <span>Name</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>nameVSpec</span><span>,</span> <span>'John'</span><span>)</span><span>;</span>
<span>const</span> <span>lastName</span>: <span>Name</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>nameVSpec</span><span>,</span> <span>'Doe'</span><span>)</span><span>;</span>

<span>type</span> <span>Name2</span> <span>=</span> <span>VString</span><span>&lt;</span><span>'1,65'</span><span>&gt;</span>
<span>const</span> <span>name2VSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Name</span><span>&gt;</span> <span>=</span> <span>'1,64'</span><span>;</span>
<span>const</span> <span>firstName2</span>: <span>Name2</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>name2VSpec</span><span>,</span> <span>'John'</span><span>)</span><span>;</span>
<span>const</span> <span>lastName2</span>: <span>Name2</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>name2VSpec</span><span>,</span> <span>'Doe'</span><span>)</span><span>;</span>

<span>// Only this will succeed where 'firstName' and 'lastName' are given in correct order with correct validated type</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>{</span> firstName <span>}</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>{</span> lastName <span>}</span><span>)</span><span>)</span><span>;</span>

<span>// These below will fail during compilation</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>{</span> lastName <span>}</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>{</span> firstName <span>}</span><span>)</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>new</span> <span>SemType</span><span>(</span><span>{</span> <span>firstName</span>: <span>firstName2</span> <span>}</span><span>)</span><span>,</span> <span>new</span> <span>SemType</span><span>(</span><span>{</span> <span>lastName</span>: <span>lastName2</span> <span>}</span><span>)</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>'John'</span><span>,</span> <span>'Doe'</span><span>)</span><span>;</span>
<span>myFunc</span><span>(</span><span>firstName</span><span>,</span> <span>lastName</span><span>)</span><span>;</span></pre></div>
<p></p><h3><a></a> Create Semantic Validated Integers</h3><a href="#-create-semantic-validated-integers"></a><p></p>
<div><pre><span>import</span> <span>{</span> <span>SemVInt</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>HttpPort</span> <span>=</span> <span>SemVInt</span><span>&lt;</span><span>'httpPort'</span><span>,</span> <span>'1,65535'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>httpPort</span>: <span>HttpPort</span> <span>=</span> <span>SemVInt</span><span>.</span><span>tryCreate</span><span>(</span><span>'httpPort'</span><span>,</span> <span>'1,65535'</span><span>,</span> <span>8080</span><span>)</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>httpPort</span><span>.</span><span>value</span><span>)</span><span>;</span> <span>// Prints 8080</span></pre></div>
<p></p><h3><a></a> Create Semantic Validated Floats</h3><a href="#-create-semantic-validated-floats"></a><p></p>
<div><pre><span>import</span> <span>{</span> <span>SemVFloat</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>LoanInterest</span> <span>=</span> <span>SemVFloat</span><span>&lt;</span><span>'loanInterest'</span><span>,</span> <span>'0,100'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>loanInterest</span>: <span>LoanInterest</span> <span>=</span> <span>SemVFloat</span><span>.</span><span>tryCreate</span><span>(</span><span>'loanInterest'</span><span>,</span> <span>'0,100'</span><span>,</span> <span>4.99</span><span>)</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>loanInterest</span><span>.</span><span>value</span><span>)</span><span>;</span> <span>// Prints 4.99</span></pre></div>
<p></p><h3><a></a> Create Semantic Validated Strings</h3><a href="#-create-semantic-validated-strings"></a><p></p>
<div><pre><span>import</span> <span>{</span> <span>SemVString</span> <span>}</span> <span>from</span> <span>'validated-types'</span><span>;</span>

<span>type</span> <span>LoginUrl</span> <span>=</span> <span>SemVString</span><span>&lt;</span><span>'loginUrl'</span><span>,</span> <span>'1,8192,url'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>loginUrl</span>: <span>LoginUrl</span> <span>=</span> <span>SemVString</span><span>.</span><span>tryCreate</span><span>(</span><span>'loginUrl'</span><span>,</span> <span>'1,8192,url'</span><span>,</span> <span>"https://server.com"</span><span>)</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>loginUrl</span><span>.</span><span>value</span><span>)</span> <span>// Prints https://server.com</span></pre></div>
<p></p><h2><a></a> API documentation</h2><a href="#-api-documentation"></a><p></p>
<p></p><h3><a></a> VFloat</h3><a href="#-vfloat"></a><p></p>
<div><pre><span>class</span> <span>VFloat</span><span>&lt;</span><span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>registerCustomValidator</span><span>(</span><span>validatorName</span>: <span>string</span><span>,</span> <span>validateFunc</span>: <span>(</span><span>value</span>: <span>number</span><span>)</span> <span>=&gt;</span> <span>boolean</span><span>)</span>: <span><span>void</span></span><span>;</span>
  
  <span>static</span> <span>createOrThrow</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VFloat</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>tryCreate</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VFloat</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>create</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VFloat</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span>
  <span>static</span> <span>createOrError</span><span>(</span>
    <span>validationSpec</span>: <span>string</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>VFloat</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span>
  <span>get</span> <span>value</span><span>(</span><span>)</span>: <span>number</span><span>;</span>
<span>}</span></pre></div>
<p></p><h4><a></a> VFloat.registerCustomValidator</h4><a href="#-vfloatregistercustomvalidator"></a><p></p>
<p><code>static registerCustomValidator(validatorName: string, validateFunc: (value: number) =&gt; boolean): void</code></p>
<p>Registers a custom validator with given name. <code>validateFunc</code> receives a float value as parameter and returns boolean based on success of validation.
You must register your custom validator before using it in any of the <code>create</code> functions.</p>
<p></p><h4><a></a>VFloat.createOrThrow and VFloat.tryCreate</h4><a href="#vfloatcreateorthrow-and-vfloattrycreate"></a><p></p>
<p><code>static createOrThrow(validationSpec: string, value: number, varName?: string): VFloat&lt;VSpec&gt; | never</code>
<code>static tryCreate(validationSpec: string, value: number, varName?: string): VFloat&lt;VSpec&gt; | never</code></p>
<p>Creates a new validated float value object or throws a <code>ValidationError</code> exception if supplied value is invalid.
<code>validationSpec</code> is a string of following form <code>'[&lt;minValue&gt;],[&lt;maxValue&gt;] | negative | positive | custom:&lt;custom_validator_name&gt;'</code>.</p>
<p><code>validationSpec</code> examples:</p>
<ul>
<li>'0,100'</li>
<li>'100,'</li>
<li>',0'</li>
<li>'positive'</li>
<li>'negative'</li>
<li>'custom:isUsShoeSize'</li>
</ul>
<p>If <code>minValue</code> is missing, <code>Number.MIN_VALUE</code> is used.
If <code>maxValue</code> is missing, <code>Number.MAX_VALUE</code> is used.
If <code>varName</code> is supplied, it is mentioned in possible <code>ValidationError</code> thrown.</p>
<p></p><h4><a></a>VFloat.create</h4><a href="#vfloatcreate"></a><p></p>
<p><code>static create(validationSpec: string, value: number, varName?: string): VFloat&lt;VSpec&gt; | null</code></p>
<p>Same as <code>VFloat.createOrThrow</code>, but instead of throwing on validation failure, it returns <code>null</code>.
This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.</p>
<p></p><h4><a></a>VFloat.createOrError</h4><a href="#vfloatcreateorerror"></a><p></p>
<p><code>static createOrError(validationSpec: string, value: number, varName?: string): [VFloat&lt;VSpec&gt;, null] | [null, Error]</code></p>
<p>Same as <code>VFloat.createOrThrow</code>, but instead of throwing on validation failure, it returns a tuple <code>[VFloat, null]</code> on success and tuple <code>[null, Error]</code> on validation failure.
This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error.
For example:</p>
<div><pre><span>const</span> <span>[</span><span>float</span><span>,</span> <span>err</span><span>]</span> <span>=</span> <span>VFloat</span><span>.</span><span>createOrError</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>1</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>err</span><span>)</span> <span>{</span>
  <span>// handle error here</span>
<span>}</span></pre></div>
<p></p><h4><a></a>value</h4><a href="#value"></a><p></p>
<p><code>get value(): number</code></p>
<p>Returns the valid float value.</p>
<p></p><h3><a></a> VInt</h3><a href="#-vint"></a><p></p>
<div><pre><span>class</span> <span>VInt</span><span>&lt;</span><span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>registerCustomValidator</span><span>(</span><span>validatorName</span>: <span>string</span><span>,</span> <span>validateFunc</span>: <span>(</span><span>value</span>: <span>number</span><span>)</span> <span>=&gt;</span> <span>boolean</span><span>)</span>: <span><span>void</span></span><span>;</span>
  <span>static</span> <span>createOrThrow</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VInt</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>tryCreate</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VInt</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>create</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VInt</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span>
  <span>static</span> <span>createOrError</span><span>(</span>
    <span>validationSpec</span>: <span>string</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>VInt</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span>
  <span>get</span> <span>value</span><span>(</span><span>)</span>: <span>number</span><span>;</span>
<span>}</span></pre></div>
<p></p><h4><a></a>VInt.registerCustomValidator</h4><a href="#vintregistercustomvalidator"></a><p></p>
<p><code>static registerCustomValidator(validatorName: string, validateFunc: (value: number) =&gt; boolean): void</code></p>
<p>Registers a custom validator with given name. <code>validateFunc</code> receives a number as parameter and returns boolean based on success of validation.
You must register your custom validator before using it in any of the <code>create</code> functions.</p>
<p></p><h4><a></a>VInt.createOrThrow and VInt.tryCreate</h4><a href="#vintcreateorthrow-and-vinttrycreate"></a><p></p>
<p><code>static createOrThrow(validationSpec: string, value: number, varName?: string): VInt&lt;VSpec&gt; | never</code>
<code>static tryCreate(validationSpec: string, value: number, varName?: string): VInt&lt;VSpec&gt; | never</code></p>
<p>Creates a new validated integer value object or throws a <code>ValidationError</code> exception if supplied value is invalid.
<code>validationSpec</code> is a string of following form <code>'[&lt;minValue&gt;],[&lt;maxValue&gt;][,&lt;divisibleByValue&gt;] | negative | positive | custom:&lt;custom_validator_name&gt;'</code>.</p>
<p><code>validationSpec</code> examples:</p>
<ul>
<li>'0,100'</li>
<li>'0,100,2'</li>
<li>'100,'</li>
<li>',0'</li>
<li>','</li>
<li>'positive'</li>
<li>'negative'</li>
<li>'custom:isEven'</li>
</ul>
<p>If <code>minValue</code> is missing, <code>Number.MIN_SAFE_INTEGER</code> is used.
If <code>maxValue</code> is missing, <code>Number.MAX_SAFE_INTEGER</code> is used.
If <code>varName</code> is supplied, it is mentioned in possible <code>ValidationError</code> thrown.</p>
<p></p><h4><a></a>VInt.create</h4><a href="#vintcreate"></a><p></p>
<p><code>static create(validationSpec: string, value: number, varName?: string): VInt&lt;VSpec&gt; | null</code></p>
<p>Same as <code>VInt.createOrThrow</code>, but instead of throwing on validation failure, it returns <code>null</code>.
This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.</p>
<p></p><h4><a></a> VInt.createOrError</h4><a href="#-vintcreateorerror"></a><p></p>
<p><code>static createOrError(validationSpec: string, value: number, varName?: string): [VInt&lt;VSpec&gt;, null] | [null, Error]</code></p>
<p>Same as <code>VInt.createOrThrow</code>, but instead of throwing on validation failure, it returns a tuple <code>[VInt, null]</code> on success and tuple <code>[null, Error]</code> on validation failure
This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error.
For example:</p>
<div><pre><span>const</span> <span>[</span><span>int</span><span>,</span> <span>err</span><span>]</span> <span>=</span> <span>VInt</span><span>.</span><span>createOrError</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>1</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>err</span><span>)</span> <span>{</span>
  <span>// handle error here</span>
<span>}</span></pre></div>
<p></p><h4><a></a> value</h4><a href="#-value"></a><p></p>
<p><code>get value(): number</code></p>
<p>Returns the valid integer value.</p>
<p></p><h3><a></a> VString</h3><a href="#-vstring"></a><p></p>
<div><pre><span>class</span> <span>VString</span><span>&lt;</span><span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>registerCustomValidator</span><span>(</span><span>validatorName</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span> <span>validateFunc</span>: <span>(</span><span>value</span>: <span>string</span><span>)</span> <span>=&gt;</span> <span>boolean</span><span>)</span>: <span><span>void</span></span><span>;</span>
  <span>static</span> <span>createOrThrow</span><span>(</span><span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VString</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>tryCreate</span><span>(</span><span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VString</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>create</span><span>(</span><span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span> <span>value</span>: <span>number</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VString</span><span>&lt;</span><span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span>
  <span>static</span> <span>createOrError</span><span>(</span>
    <span>validationSpec</span>: <span>string</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>VString</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span>
  <span>get</span> <span>value</span><span>(</span><span>)</span>: <span>string</span><span>;</span>
<span>}</span></pre></div>
<p></p><h4><a></a>VString.registerCustomValidator</h4><a href="#vstringregistercustomvalidator"></a><p></p>
<p><code>static registerCustomValidator(validatorName: string, validateFunc: (value: string) =&gt; boolean): void</code></p>
<p>Registers a custom validator with given name. <code>validateFunc</code> receives a string value as parameter and returns boolean based on success of validation.
You must register your custom validator before using it in any of the <code>create</code> functions.</p>
<p></p><h4><a></a>VString.createOrThrow and VString.tryCreate</h4><a href="#vstringcreateorthrow-and-vstringtrycreate"></a><p></p>
<p><code>static createOrThrow(validationSpec: string, value: number, varName?: string): VString&lt;VSpec&gt; | never</code>
<code>static tryCreate(validationSpec: string, value: number, varName?: string): VString&lt;VSpec&gt; | never</code></p>
<p>Creates a new validated integer value object or throws a <code>ValidationError</code> exception if supplied value is invalid.
<code>validationSpec</code> is a string of following form <code>'[&lt;minLength&gt;],&lt;maxLength&gt;[,&lt;unknown_length_validator_name&gt;[,&lt;parameter&gt;]] | &lt;known_length_validator_name&gt; | custom:&lt;custom_validator_name&gt;'</code>.</p>
<p>Possible value for <code>&lt;unknown_length_validator_name&gt;</code>:</p>
<ul>
<li>alpha</li>
<li>alphanumeric</li>
<li>ascii</li>
<li>base32</li>
<li>base58</li>
<li>base64</li>
<li>dataUri</li>
<li>decimal</li>
<li>fqdn</li>
<li>md4</li>
<li>md5</li>
<li>sha1</li>
<li>sha256</li>
<li>sha384</li>
<li>sha512</li>
<li>crc32</li>
<li>crc32b</li>
<li>hex</li>
<li>ipv4Range</li>
<li>ipv6Range</li>
<li>json</li>
<li>lowercase</li>
<li>magnetUri</li>
<li>mongoId</li>
<li>numeric</li>
<li>octal</li>
<li>uppercase</li>
<li>strongPassword</li>
<li>url</li>
<li>includes (requires <code>parameter</code>)</li>
<li>match (requires a RegExp string <code>parameter</code>)</li>
<li>isOneOf (requires JSON string array <code>parameter</code>)</li>
<li>isNoneOf (requires JSON string array <code>parameter</code>)</li>
<li>startsWith (requires <code>parameter</code>)</li>
<li>endsWith (requires <code>parameter</code>)</li>
<li>numericRange (requires <code>parameter</code>in format: <code>&lt;minValue&gt;-&lt;maxValue&gt;</code>, e.g. 1-65535)</li>
</ul>
<p>Possible values for <code>&lt;known_length_validator_name&gt;</code>:</p>
<ul>
<li>boolean</li>
<li>bic</li>
<li>btcAddress</li>
<li>creditCard</li>
<li>ean</li>
<li>email</li>
<li>ethereumAddress</li>
<li>hsl</li>
<li>hexColor</li>
<li>isin</li>
<li>iban</li>
<li>ipv4</li>
<li>ipv6</li>
<li>iso31661Alpha2</li>
<li>iso31661Alpha3</li>
<li>iso8601</li>
<li>isrc</li>
<li>issn</li>
<li>jwt</li>
<li>latLong</li>
<li>macAddress</li>
<li>mimeType</li>
<li>port</li>
<li>rgbColor</li>
<li>semVer</li>
<li>uuid</li>
<li>postalCode</li>
<li>creditCardExpiration</li>
<li>cvc</li>
<li>mobileNumber</li>
</ul>
<p>More information about validators can be found in <a href="https://github.com/validatorjs/validator.js/">validator.js documentation</a>
If you need a new built-in validator, please <a href="https://github.com/pksilen/validated-types/issues">open a new issue</a> about that.</p>
<p><code>validationSpec</code> examples:</p>
<ul>
<li>'0,100'</li>
<li>',100'</li>
<li>'1,1024,url'</li>
<li>'1,1024,startsWith,https'</li>
<li>'email'</li>
<li>'custom:isSupplierName'</li>
</ul>
<p>If <code>minLength</code> is missing, 0 is used.
If <code>varName</code> is supplied, it is mentioned in possible <code>ValidationError</code> thrown.</p>
<p></p><h4><a></a>VString.create</h4><a href="#vstringcreate"></a><p></p>
<p><code>static create(validationSpec: string, value: number, varName?: string): VString&lt;VSpec&gt; | null</code></p>
<p>Same as <code>VString.createOrThrow</code>, but instead of throwing on validation failure, it returns <code>null</code>.
This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.</p>
<p></p><h4><a></a>VString.createOrError</h4><a href="#vstringcreateorerror"></a><p></p>
<p><code>static createOrError(validationSpec: string, value: number, varName?: string): [VString&lt;VSpec&gt;, null] | [null, Error]</code></p>
<p>Same as <code>VString.createOrThrow</code>, but instead of throwing on validation failure, it returns a tuple <code>[VString, null]</code> on success and tuple <code>[null, Error]</code> on validation failure
This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error.
For example:</p>
<div><pre><span>const</span> <span>[</span><span>str</span><span>,</span> <span>err</span><span>]</span> <span>=</span> <span>VString</span><span>.</span><span>createOrError</span><span>&lt;</span><span>'1,10'</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>'abc'</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>err</span><span>)</span> <span>{</span>
  <span>// handle error here</span>
<span>}</span></pre></div>
<p></p><h4><a></a>value</h4><a href="#value-1"></a><p></p>
<p><code>get value(): string</code></p>
<p>Returns the valid string value.</p>
<p></p><h3><a></a> VArray</h3><a href="#-varray"></a><p></p>
<p><code>T</code> is the type of elements in the array.</p>
<div><pre><span>class</span> <span>VArray</span><span>&lt;</span><span>VSpec</span> <span>extends</span> <span>string</span><span>,</span> <span>T</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>registerCustomValidator</span><span>(</span><span>validatorName</span>: <span>string</span><span>,</span> <span>validateFunc</span>: <span>(</span><span>value</span>: <span>T</span><span>[</span><span>]</span><span>)</span> <span>=&gt;</span> <span>boolean</span><span>)</span>: <span><span>void</span></span><span>;</span>
  <span>static</span> <span>createOrThrow</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>T</span><span>[</span><span>]</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VArray</span><span>&lt;</span><span>VSpec</span><span>,</span> <span>T</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>tryCreate</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>T</span><span>[</span><span>]</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VArray</span><span>&lt;</span><span>VSpec</span><span>,</span> <span>T</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span>
  <span>static</span> <span>create</span><span>(</span><span>validationSpec</span>: <span>string</span><span>,</span> <span>value</span>: <span>T</span><span>[</span><span>]</span><span>,</span> <span>varName</span>?: <span>string</span><span>)</span>: <span>VArray</span><span>&lt;</span><span>VSpec</span><span>,</span> <span>T</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span>
  <span>static</span> <span>createOrError</span><span>(</span>
    <span>validationSpec</span>: <span>string</span><span>,</span>
    <span>value</span>: <span>T</span><span>[</span><span>]</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>VArray</span><span>&lt;</span><span>VSpec</span><span>,</span> <span>T</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span>
  <span>get</span> <span>value</span><span>(</span><span>)</span>: <span>T</span><span>[</span><span>]</span><span>;</span>
<span>}</span></pre></div>
<p></p><h4><a></a> VArray.registerCustomValidator</h4><a href="#-varrayregistercustomvalidator"></a><p></p>
<p><code>static registerCustomValidator(validatorName: string, validateFunc: (value: T[]) =&gt; boolean): void</code></p>
<p>Registers a custom validator with given name. <code>validateFunc</code> receives an array as parameter and returns boolean based on success of validation.
You must register your custom validator before using it in any of the <code>create</code> functions.</p>
<p></p><h4><a></a>VArray.createOrThrow and VArray.tryCreate</h4><a href="#varraycreateorthrow-and-varraytrycreate"></a><p></p>
<p><code>static createOrThrow(validationSpec: string, value: T[], varName?: string): VArray&lt;VSpec, T&gt; | never</code>
<code>static tryCreate(validationSpec: string, value: T[], varName?: string): VArray&lt;VSpec, T&gt; | never</code></p>
<p>Creates a new validated array value object or throws a <code>ValidationError</code> exception if supplied value is invalid.
<code>validationSpec</code> is a string of following form <code>'[&lt;minLength&gt;],&lt;maxLength&gt;[,unique] | custom:&lt;custom_validator_name&gt;'</code>.</p>
<p><code>validationSpec</code> examples:</p>
<ul>
<li>'0,100'</li>
<li>',100'</li>
<li>'1,10,unique'</li>
<li>'custom:includesSomething'</li>
</ul>
<p>If <code>minLength</code> is missing, 0 is used.
If <code>varName</code> is supplied, it is mentioned in possible <code>ValidationError</code> thrown.</p>
<p></p><h4><a></a>VArray.create</h4><a href="#varraycreate"></a><p></p>
<p><code>static create(validationSpec: string, value: T[], varName?: string): VArray&lt;VSpec, T&gt; | null</code></p>
<p>Same as <code>VFloat.createOrThrow</code>, but instead of throwing on validation failure, it returns <code>null</code>.
This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.</p>
<p></p><h4><a></a>VArray.createOrError</h4><a href="#varraycreateorerror"></a><p></p>
<p><code>static createOrError(validationSpec: string, value: T[], varName?: string): [VArray&lt;VSpec, T&gt;, null] | [null, Error]</code></p>
<p>Same as <code>VFloat.createOrThrow</code>, but instead of throwing on validation failure, it returns a tuple <code>[VArray, null]</code> on success and tuple <code>[null, Error]</code> on validation failure.
This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error.
For example:</p>
<div><pre><span>const</span> <span>[</span><span>array</span><span>,</span> <span>err</span><span>]</span> <span>=</span> <span>VArray</span><span>.</span><span>createOrError</span><span>&lt;</span><span>'1,10'</span><span>,</span> <span>number</span><span>&gt;</span><span>(</span><span>'1,10'</span><span>,</span> <span>[</span><span>1</span><span>]</span><span>)</span><span>;</span>
<span>if</span> <span>(</span><span>err</span><span>)</span> <span>{</span>
  <span>// handle error here</span>
<span>}</span></pre></div>
<p></p><h4><a></a>value</h4><a href="#value-2"></a><p></p>
<p><code>get value(): T[]</code></p>
<p>Returns the validated array.</p>
<p></p><h3><a></a> SemType</h3><a href="#-semtype"></a><p></p>
<p><code>T</code> is the type of Semantic variable.</p>
<div><pre><span>type</span> <span>SemName</span><span>&lt;</span><span>N</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>=</span> <span>N</span> <span>extends</span> `${infer <span>Name</span><span>}</span>` ? `${<span>Name</span><span>}</span>` : <span>never</span><span>;</span>

<span>class</span> <span>SemType</span><span>&lt;</span><span>T</span><span>,</span> <span>N</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>constructor</span><span>(</span><span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>N</span><span>&gt;</span><span>,</span> <span>value</span>: <span>T</span><span>)</span><span>;</span>
  <span>constructor</span><span>(</span><span>semType</span>: <span>{</span> <span>[</span><span>K</span> <span>in</span> <span>SemName</span><span>&lt;</span><span>N</span><span>&gt;</span><span>]</span>: <span>T</span> <span>}</span><span>)</span><span>;</span>
  <span>get</span> <span>value</span><span>(</span><span>)</span>: <span>T</span><span>;</span>
<span>}</span></pre></div>
<p></p><h4><a></a> constructor</h4><a href="#-constructor"></a><p></p>
<p><code>constructor(semanticName: SemName&lt;N&gt;, value: T)</code><br/>
<code>constructor(semType: { [K in SemName&lt;N&gt;]: T });</code></p>
<p>Creates a new semantic variable with semantic name <code>semanticName</code> and with value of type <code>T</code>.</p>
<p></p><h4><a></a> value</h4><a href="#-value-1"></a><p></p>
<p><code>get value(): T</code>
Get the value of semantic variable.</p>
<p></p><h3><a></a> SemVInt</h3><a href="#-semvint"></a><p></p>
<div><pre><span>type</span> <span>SemName</span><span>&lt;</span><span>N</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>=</span> <span>N</span> <span>extends</span> `${infer <span>Name</span><span>}</span>` ? `${<span>Name</span><span>}</span>` : <span>never</span><span>;</span>

<span>class</span> <span>SemVInt</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>tryCreate</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>IntValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>SemVInt</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span> <span>// Throws on error</span>

  <span>static</span> <span>create</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>IntValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span>
  <span>)</span>: <span>SemVInt</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span> <span>// Returns null on error</span>

  <span>static</span> <span>createOrError</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>IntValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>SemVInt</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span> <span>// Returns a pair [null, Error] on error</span>
<span>}</span></pre></div>
<p></p><h3><a></a> SemVFloat</h3><a href="#-semvfloat"></a><p></p>
<div><pre><span>type</span> <span>SemName</span><span>&lt;</span><span>N</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>=</span> <span>N</span> <span>extends</span> `${infer <span>Name</span><span>}</span>` ? `${<span>Name</span><span>}</span>` : <span>never</span><span>;</span>

<span>class</span> <span>SemVFloat</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>tryCreate</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>FloatValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>SemVFloat</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span> <span>// Throws on error</span>

  <span>static</span> <span>create</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>FloatValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span>
  <span>)</span>: <span>SemVFloat</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span> <span>// Returns null on error</span>

  <span>static</span> <span>createOrError</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>FloatValidationSpec</span><span>&lt;</span><span>VSpec</span><span>&gt;</span><span>,</span>
    <span>value</span>: <span>number</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>SemVFloat</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span> <span>// Returns a pair [null, Error] on error</span>
<span>}</span></pre></div>
<p></p><h3><a></a> SemVString</h3><a href="#-semvstring"></a><p></p>
<div><pre><span>type</span> <span>SemName</span><span>&lt;</span><span>N</span> <span>extends</span> <span>string</span><span>&gt;</span> <span>=</span> <span>N</span> <span>extends</span> `${infer <span>Name</span><span>}</span>` ? `${<span>Name</span><span>}</span>` : <span>never</span><span>;</span>

<span>class</span> <span>SemVString</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>&gt;</span> <span>{</span>
  <span>static</span> <span>tryCreate</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span>
    <span>value</span>: <span>string</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>SemVString</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>never</span><span>;</span> <span>// Throws on error</span>

  <span>static</span> <span>create</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span>
    <span>value</span>: <span>string</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>SemVString</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span> <span>|</span> <span>null</span><span>;</span> <span>// Returns null on error</span>

  <span>static</span> <span>createOrError</span><span>&lt;</span><span>Name</span> <span>extends</span> <span>string</span><span>,</span> <span>VSpec</span> <span>extends</span> <span>string</span><span>&gt;</span><span>(</span>
    <span>semanticName</span>: <span>SemName</span><span>&lt;</span><span>Name</span><span>&gt;</span><span>,</span>
    <span>validationSpec</span>: <span>string</span> <span>|</span> <span>string</span><span>[</span><span>]</span><span>,</span>
    <span>value</span>: <span>string</span><span>,</span>
    <span>varName</span>?: <span>string</span>
  <span>)</span>: <span>[</span><span>SemVString</span><span>&lt;</span><span>Name</span><span>,</span> <span>VSpec</span><span>&gt;</span><span>,</span> <span>null</span><span>]</span> <span>|</span> <span>[</span><span>null</span><span>,</span> <span>Error</span><span>]</span><span>;</span> <span>// Returns a pair [null, Error] on error</span>
<span>}</span></pre></div>
<p></p><h3><a></a> VSpecOf</h3><a href="#-vspecof"></a><p></p>
<p>Extracts the validation spec type of the validated type.</p>
<p>For example:</p>
<div><pre><span>type</span> <span>Month</span> <span>=</span> <span>VInt</span><span>&lt;</span><span>'1,12'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>monthVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Month</span><span>&gt;</span> <span>=</span> <span>'1,12'</span><span>;</span>
<span>const</span> <span>month</span>: <span>Month</span> <span>=</span> <span>VInt</span><span>.</span><span>tryCreate</span><span>(</span><span>monthVSpec</span><span>,</span> <span>1</span><span>)</span><span>;</span>

<span>type</span> <span>Percent</span> <span>=</span> <span>VFloat</span><span>&lt;</span><span>'0,100'</span><span>&gt;</span><span>;</span>
<span>const</span> <span>percentVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Percent</span><span>&gt;</span> <span>=</span> <span>'0,100'</span><span>;</span>
<span>const</span> <span>percent</span>: <span>Percent</span> <span>=</span> <span>VFloat</span><span>.</span><span>tryCreate</span><span>(</span><span>percentVSpec</span><span>,</span> <span>25.0</span><span>)</span><span>;</span>

<span>type</span> <span>Url</span> <span>=</span> <span>VString</span><span>&lt;</span><span>[</span><span>'1,1024,lowercase'</span><span>,</span> <span>'url'</span><span>,</span> <span>'startsWith,https'</span><span>,</span> <span>'endsWith,.html'</span><span>]</span><span>&gt;</span><span>;</span>
<span>const</span> <span>urlVSpec</span>: <span>VSpecOf</span><span>&lt;</span><span>Url</span><span>&gt;</span> <span>=</span> <span>[</span><span>'1,1024,lowercase'</span><span>,</span> <span>'url'</span><span>,</span> <span>'startsWith,https'</span><span>,</span> <span>'endsWith,.html'</span><span>]</span><span>;</span>
<span>const</span> <span>url</span>: <span>Url</span> <span>=</span> <span>VString</span><span>.</span><span>tryCreate</span><span>(</span><span>urlVSpec</span><span>,</span> <span>'https://server.domain.com:8080/index.html'</span><span>)</span><span>;</span></pre></div>
<p></p><h2><a></a> Feedback</h2><a href="#-feedback"></a><p></p>
<p>If you want to report a bug, please <a href="https://github.com/pksilen/validated-types/issues">create a new issue</a> about that.</p>
<p>If you want to request a new feature, for example, a new type of validator for string, please <a href="https://github.com/pksilen/validated-types/issues">create a new issue</a> about that.</p>
<p></p><h2><a></a> License</h2><a href="#-license"></a><p></p>
<p><a href="https://github.com/pksilen/validated-types/blob/main/LICENSE">MIT</a></p>
</article></div></div>||||I||||    Skip to content

    Navigation Menu

    Toggle navigation
          Sign in
            * Product
                        + Actions
                        Automate any workflow
                        + Packages
                        Host and manage packages
                        + Security
                        Find and fix vulnerabilities
                        + Codespaces
                        Instant dev environments
                        + GitHub Copilot
                        Write better code with AI
                        + Code review
                        Manage code changes
                        + Issues
                        Plan and track work
                        + Discussions
                        Collaborate outside of code
                  Explore
                    + All features
                    + Documentation
                    + GitHub Skills
                    + Blog
            * Solutions
                  By size
                    + Enterprise
                    + Teams
                    + Startups
                  By industry
                    + Healthcare
                    + Financial services
                    + Manufacturing
                  By use case
                    + CI/CD & Automation
                    + DevOps
                    + DevSecOps
            * Resources
                  Topics
                    + AI
                    + DevOps
                    + Security
                    + Software Development
                  Explore
                    + Learning Pathways
                    + White papers, Ebooks, Webinars
                    + Customer Stories
                    + Partners
            * Open Source
                        + GitHub Sponsors
                        Fund open source developers
                        + The ReadME Project
                        GitHub community articles
                  Repositories
                    + Topics
                    + Trending
                    + Collections
            * Enterprise
                        + Enterprise platform
                        AI-powered developer platform
                  Available add-ons
                        + Advanced Security
                        Enterprise-grade security features
                        + GitHub Copilot
                        Enterprise-grade AI features
                        + Premium Support
                        Enterprise-grade 24/7 support
            * Pricing
              Search or jump to...

                Search code, repositories, users, issues, pull requests...

                        Search
                          Clear
                        Search syntax tips

                    Provide feedback

                We read every piece of feedback, and take your input very seriously.

                Include my email address so I can be contacted
                Cancel Submit feedback

                    Saved searches

                    Use saved searches to filter your results more quickly

                    Name
                    Query

                  To see all available qualifiers, see our documentation.

                Cancel Create saved search
              Sign in
            Sign up Reseting focus
      You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert
            {{ message }}
              pksilen / validated-types Public
              * Notifications You must be signed in to change notification settings
              * Fork 3
                * Star 18

            Library for creating validated Typescript types for integers, floats, string and arrays

            License

              MIT license
              18 stars 3 forks Branches Tags Activity
                  Star
                Notifications You must be signed in to change notification settings
          * Code
          * Issues 1
          * Pull requests 0
          * Actions
          * Projects 0
          * Security
          * Insights
          Additional navigation options
                  * Code
                  * Issues
                  * Pull requests
                  * Actions
                  * Projects
                  * Security
                  * Insights

        pksilen/validated-types

                  This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
                              main
                          Branches Tags
                            Go to file
                        Code

                        Folders and files

                          Name                            Name                              Last commit message    Last commit date
                            Latest commit               
                                                        
                                History                 
                                                        
                                126 Commits             
                                  .circleci                       .circleci                                                        
                                  .husky                          .husky                                                           
                                  .idea                           .idea                                                            
                                  src                             src                                                              
                                  .eslintrc.json                  .eslintrc.json                                                   
                                  .gitignore                      .gitignore                                                       
                                  .prettierrc                     .prettierrc                                                      
                                  .sonarcloud.properties          .sonarcloud.properties                                           
                                  LICENSE                         LICENSE                                                          
                                  README.MD                       README.MD                                                        
                                  package-lock.json               package-lock.json                                                
                                  package.json                    package.json                                                     
                                  tsconfig.json                   tsconfig.json                                                    
                            View all files              
                          

                              Repository files navigation

                                * README
                                * MIT license

                                validated-types

                              validated-types is a library for Typescript to create types for validated integer, float, string and array values. It also allows of creating semantic types and declare variables with semantic types.

                                Table of Contents

                                * Prerequisites
                                * Installation
                                * Usage
                                    + Introduction
                                    + Validate Integers
                                    + Validate Floats
                                    + Validate Strings
                                    + Validate Arrays
                                    + Validate Objects
                                    + Create Semantic Types/Variables
                                    + Create Semantic Validated Integers
                                    + Create Semantic Validated Floats
                                    + Create Semantic Validated Strings
                                * API Documentation
                                    + VFloat
                                        o registerCustomValidator
                                        o createOrThrow
                                        o create
                                        o createOrError
                                        o value
                                    + VInt
                                        o registerCustomValidator
                                        o createOrThrow
                                        o create
                                        o createOrError
                                        o value
                                    + VString
                                        o registerCustomValidator
                                        o createOrThrow
                                        o create
                                        o createOrError
                                        o value
                                    + VArray
                                        o registerCustomValidator
                                        o createOrThrow
                                        o create
                                        o createOrError
                                        o value
                                    + SemType
                                        o constructor
                                        o value
                                    + SemVInt
                                    + SemVFloat
                                    + SemVString
                                    + VSpecOf
                                * Feedback
                                * License

                                Prerequisites

                                * Typescript >= 4.1.0

                                Installation

                                npm install --save validated-types

                                Usage

                                Introduction

                              Validated-types is a type value validation library for Typescript. You can validate values of integers, floats, strings and arrays. For numbers, you can for example validate the minimum and maximum value. For strings, you can validate the length and also perform semantic validation to validate if a string should be, for example, a valid URL, IP address or email address.

                              By using validated types for the parameters of your application's functions, you can rest assured that only proper values are ever passed to your function. You don't have to do any validation work inside your functions, just use the value of already validated parameter. The validation of the value is done only once upon the construction of validated objects, so there is no performance penalty in using the validated values as many times as you need.

                              You should create the validated integer, float, string and array objects in functions that receive unvalidated input data and then pass the validated values to the rest of the functions in your application.

                              Your application typically receives unvalidated input data from external sources in following scenarios:

                                * Reading command line arguments
                                * Reading environment variables
                                * Reading standard input
                                * Reading file(s) from file system
                                * Reading data from socket (network input)
                                * End-user input from user interface

                              You can also create semantic types and semantically typed variables using SemType. Using semantic types, you can differentiate between multiple types of the same basic type. For example, If a function accepts two boolean arguments, it is possible that the calling function gives those two arguments in wrong order, but you never notice it, because it does not generate a compilation error. Using semantic types, you can differentiate between those two boolean types by giving them two different semantic names. Semantic name is just any string describing the purpose of type/variable.

                              The library contains static factory methods in the classes forr creating a new instance of the specific class. There are different factory methods available. You can choose which factory method to use depending on your application need. The factory methods are following:

                                * tryCreate(...) creates a validated value object or throws an exception
                                * createOrThrow(...) is same as above, i.e. creates a validated value object or throws an exception
                                * create(...) creates a validated value object or returns null. Use this method if you don't need the error reason
                                * createOrError(...) creates a validated value object or returns an error object, always returns a pair (is similar to Golang returning an error)

                                Validate Integers

                              You can validate your integer, float and string type variables with validated-types. For example, to create a validated integer which allows values between 1 and 10, you declare:

                                import { VInt } from 'validated-types';
                                
                                function useInt(int: VInt<'1,10'>) {
                                  // use int here
                                  console.log(int.value);
                                }
                                
                                const int = VInt.tryCreate<'1,10'>('1,10', 5);
                                const maybeInt = VInt.create<'1,10'>('1,10', 12); // Returns null
                                
                                useInt(int); // prints to console: 5
                                useInt(maybeInt ?? VInt.tryCreate('1,10', 10)); // prints to console: 10

                              You can also register a custom validator:

                                import { VInt } from 'validated-types';
                                
                                VInt.registerCustomValidator('isEven', (value) => value % 2 === 0);
                                
                                const evenNumber = VInt.tryCreate<'custom:isEven'>('custom:isEven', 2);
                                const maybeEvenNumber = VInt<'custom:isEven'>.create('custom:isEven', 1);

                              Custom validator must be registered before it is used by any validated types create, createOrThrow or createOrErrormethod. This means that you should register your custom validators as early as possible in your application code. If custom validator is not registered, and it is used, an exception will be thrown.

                                Validate Floats

                              To create a validated float which allows positive values only, you declare:

                                import { VFloat } from 'validated-types';
                                
                                function useFloat(float: VFloat<'positive'>) {
                                  // use float here
                                  console.log(float.value);
                                }
                                
                                const float = VFloat.tryCreate<'positive'>('positive', 5.25);
                                const maybeFloat = VFloat<'positive'>.create('positive', -5.25); // returns null
                                
                                useFloat(float); // prints to console: 5.25
                                useFloat(maybeFloat ?? VFloat.tryCreate('positive', 1)); // prints to console: 1

                                Validate Strings

                              To create a validated string which allows URLs with minimum length of one and maximum length of 1024 characters, you declare:

                                import { VString } from 'validated-types';
                                
                                function useUrl(url: VString<'1,1024,url'>) {
                                  // use URL here
                                  console.log(url.value);
                                }
                                
                                const url = VString.tryCreate<'1,1024,url'>('1,1024,url', 'https://www.mydomain.com');
                                const maybeUrl = VString<'1,1024,url'>.create('1,1024,url', 'invalid URL'); // Returns null
                                
                                useUrl(url); // prints to console: https://www.mydomain.com
                                useUrl(maybeUrl ?? VString.tryCreate('1,1024,url', 'https://google.com')); // prints to console: https://google.com

                              You can combine up to 5 different string validators together. Multiple validators are given as a tuple which can have 2-5 elements. The first element of the tuple should validate the length of the string, if needed. Rest of the elements in tuple should not validate the length of string anymore. Below example contains 4 validators that validate following string:

                                * is at least 1 characters long
                                * is at most 1024 characters long
                                * is lower case string
                                * is valid URL
                                * URL starts with https
                                * URL ends with .html
                                import { SpecOf, VString } from 'validated-types';
                                
                                type Url = VString<['1,1024,lowercase', 'url', 'startsWith,https', 'endsWith,.html']>;
                                const urlVSpec: VSpecOf<Url> = ['1,1024,lowercase', 'url', 'startsWith,https', 'endsWith,.html'];
                                
                                function useUrl(url: Url) {
                                  // use URL here
                                  console.log(url.value);
                                }
                                
                                const url: Url = VString.tryCreate(urlVSpec, 'https://server.domain.com:8080/index.html');
                                const maybeUrl: Url | null = VString.create(urlVSpec, 'invalid URL'); // Returns null
                                
                                useUrl(url); // prints to console: https://server.domain.com:8080/index.html
                                useUrl(maybeUrl ?? VString.tryCreate(urlVSpec, 'https://server.domain.com:8080/index.html')); // prints to console: https://server.domain.com:8080/index.html

                                Validate Arrays

                              To create a validated array of numbers which allows array length to be from 0 to 10 and requires all array elements to be unique, you declare:

                                import { VArray } from 'validated-types';
                                
                                function useArray(array: VArray<'0,10,unique', number>) {
                                  // use array here
                                  console.log(array.value);
                                }
                                
                                const array = VArray.tryCreate<'0,10,unique', number>('0,10,unique', [1, 2, 3]);
                                const maybeArray = VArray<'0,10,unique', number>.create('0,10,unique', [1, 2, 2]);
                                
                                useArray(array); // prints to console: [1, 2, 3]
                                useArray(maybeArray ?? VArray.tryCreate('0,10,unique', [3, 4, 5])); // prints to console: [3, 4, 5]

                              You can also create an array of validated objects, for example below example validates an array of from 1 to max 10 unique email addresses:

                                import { VArray } from 'validated-types';
                                
                                type EmailAddresses =  VArray<'1,10,unique', VString<'email'>>;
                                const emailAddressesVSpec: VSpecOf<EmailAddresses> = '1,10,unique';
                                
                                function sendEmails(emailAddresses: EmailAddresses, subject: string, body: string) {
                                  console.log(emailAddresses.forEach(emailAddress=> emailAddress.value));
                                }
                                
                                const emailAddress = VString.tryCreate<'email'>('email', 'test@example.com');
                                const emailAddress2 = VString.tryCreate<'email'>('email', 'test2@example.com');
                                const emailAddresses: EmailAddresses = VArray.tryCreate(emailAddressesVSpec, [emailAddress, emailAddress2]);
                                
                                sendEmails(emailAddresses, 'subj', 'body'); // prints to console: 'test@example.com' and 'test2@example.com'

                                Validate Objects

                              You can also create validated objects, for example:

                                type Person = {
                                  firstName: VString<1, 64>;
                                  lastName: VString<1, 64>;
                                  nickNames: VString<1, 64>[];
                                  email: VString<'email'>;
                                  password: VString<'8,1024,strongPassword'>;
                                  age: VInt<0, 255>;
                                  interestPercent: VFloat<'0,100'>;
                                };

                              You can assign type aliases to your validated types:

                              types.ts

                                import { VFloat, VInt, VString } from 'validated-types';
                                
                                export type Name = VString<1, 64>;
                                export type Email = VString<'email'>;
                                export type Password = VString<'8,1024,strongPassword'>;
                                export type Age = VInt<0, 255>;
                                export type Percent = VFloat<'0,100'>;

                              person.ts

                                import { Age, Email, Name, Password, Percent } from 'types';
                                
                                type Person = {
                                  firstName: Name;
                                  lastName: Name;
                                  nickNames: Name[];
                                  email: Email;
                                  password: Password;
                                  age: Age;
                                  interestPercent: Percent;
                                };

                                Create Semantic Types/Variables

                              Semantic types and variables let you differentiate between variables of same type. The differentiation is done by assigning a semantic name to the type. Following example declares two semantic variables of boolean type with two different semantic names.

                                import { SemType } from 'validated-types';
                                
                                type IsRecursiveCall = SemType<boolean, 'isRecursiveCall'>
                                type IsInternalCall = SemType<boolean, 'isInternalCall'>;
                                
                                function myFunc(isRecursiveCall: IsRecursiveCall, isInternalCall: IsInternalCall) {
                                  console.log(isRecursiveCall.value);
                                  console.log(isInternalCall.value);
                                }
                                
                                const isRecursiveCall = false;
                                const isInternalCall = true;
                                
                                // Only this will succeed
                                myFunc(new SemType({ isRecursiveCall }), new SemType({ isInternalCall }));
                                
                                // These will fail during compilation
                                myFunc(new SemType({ isInternalCall }), new SemType({ isRecursiveCall }));
                                myFunc(true, true);
                                myFunc(new SemType('isSomethingElse', true), new SemType('isInternalCall', true));
                                myFunc(new SemType('isRecursiveCall', false), new SemType('isSomethingElse', true));
                                myFunc(new SemType('isSomethingElse', true), new SemType('isSomethingElse', true));

                              You can use a validated type as a semantic type also. In the below example, a function takes two semantic parameters which both have the same base type VString<'1,64'>.

                                import { SemType, VString } from 'validated-types';
                                
                                type Name = VString<'1,64'>;
                                const nameVSpec: VSpecOf<Name> = '1,64';
                                type FirstName = SemType<Name, 'firstName'>;
                                type LastName = SemType<Name, 'lastName'>;
                                
                                function myFunc(firstName: FirstName, lastName: LastName) {
                                  console.log(firstName.value);
                                  console.log(lastName.value);
                                }
                                
                                const firstName: Name = VString.tryCreate(nameVSpec, 'John');
                                const lastName: Name = VString.tryCreate(nameVSpec, 'Doe');
                                
                                type Name2 = VString<'1,65'>
                                const name2VSpec: VSpecOf<Name> = '1,64';
                                const firstName2: Name2 = VString.tryCreate(name2VSpec, 'John');
                                const lastName2: Name2 = VString.tryCreate(name2VSpec, 'Doe');
                                
                                // Only this will succeed where 'firstName' and 'lastName' are given in correct order with correct validated type
                                myFunc(new SemType({ firstName }), new SemType({ lastName }));
                                
                                // These below will fail during compilation
                                myFunc(new SemType({ lastName }), new SemType({ firstName }));
                                myFunc(new SemType({ firstName: firstName2 }), new SemType({ lastName: lastName2 }));
                                myFunc('John', 'Doe');
                                myFunc(firstName, lastName);

                                Create Semantic Validated Integers

                                import { SemVInt } from 'validated-types';
                                
                                type HttpPort = SemVInt<'httpPort', '1,65535'>;
                                const httpPort: HttpPort = SemVInt.tryCreate('httpPort', '1,65535', 8080);
                                console.log(httpPort.value); // Prints 8080

                                Create Semantic Validated Floats

                                import { SemVFloat } from 'validated-types';
                                
                                type LoanInterest = SemVFloat<'loanInterest', '0,100'>;
                                const loanInterest: LoanInterest = SemVFloat.tryCreate('loanInterest', '0,100', 4.99);
                                console.log(loanInterest.value); // Prints 4.99

                                Create Semantic Validated Strings

                                import { SemVString } from 'validated-types';
                                
                                type LoginUrl = SemVString<'loginUrl', '1,8192,url'>;
                                const loginUrl: LoginUrl = SemVString.tryCreate('loginUrl', '1,8192,url', "https://server.com");
                                console.log(loginUrl.value) // Prints https://server.com

                                API documentation

                                VFloat

                                class VFloat<VSpec extends string> {
                                  static registerCustomValidator(validatorName: string, validateFunc: (value: number) => boolean): void;
                                  
                                  static createOrThrow(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | never;
                                  static tryCreate(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | never;
                                  static create(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | null;
                                  static createOrError(
                                    validationSpec: string,
                                    value: number,
                                    varName?: string
                                  ): [VFloat<VSpec>, null] | [null, Error];
                                  get value(): number;
                                }

                                VFloat.registerCustomValidator

                              static registerCustomValidator(validatorName: string, validateFunc: (value: number) => boolean): void

                              Registers a custom validator with given name. validateFunc receives a float value as parameter and returns boolean based on success of validation. You must register your custom validator before using it in any of the create functions.

                                VFloat.createOrThrow and VFloat.tryCreate

                              static createOrThrow(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | never static tryCreate(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | never

                              Creates a new validated float value object or throws a ValidationError exception if supplied value is invalid. validationSpec is a string of following form '[<minValue>],[<maxValue>] | negative | positive | custom:<custom_validator_name>'.

                              validationSpec examples:

                                * '0,100'
                                * '100,'
                                * ',0'
                                * 'positive'
                                * 'negative'
                                * 'custom:isUsShoeSize'

                              If minValue is missing, Number.MIN_VALUE is used. If maxValue is missing, Number.MAX_VALUE is used. If varName is supplied, it is mentioned in possible ValidationError thrown.

                                VFloat.create

                              static create(validationSpec: string, value: number, varName?: string): VFloat<VSpec> | null

                              Same as VFloat.createOrThrow, but instead of throwing on validation failure, it returns null. This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.

                                VFloat.createOrError

                              static createOrError(validationSpec: string, value: number, varName?: string): [VFloat<VSpec>, null] | [null, Error]

                              Same as VFloat.createOrThrow, but instead of throwing on validation failure, it returns a tuple [VFloat, null] on success and tuple [null, Error] on validation failure. This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error. For example:

                                const [float, err] = VFloat.createOrError<'1,10'>('1,10', 1);
                                if (err) {
                                  // handle error here
                                }

                                value

                              get value(): number

                              Returns the valid float value.

                                VInt

                                class VInt<VSpec extends string> {
                                  static registerCustomValidator(validatorName: string, validateFunc: (value: number) => boolean): void;
                                  static createOrThrow(validationSpec: string, value: number, varName?: string): VInt<VSpec> | never;
                                  static tryCreate(validationSpec: string, value: number, varName?: string): VInt<VSpec> | never;
                                  static create(validationSpec: string, value: number, varName?: string): VInt<VSpec> | null;
                                  static createOrError(
                                    validationSpec: string,
                                    value: number,
                                    varName?: string
                                  ): [VInt<VSpec>, null] | [null, Error];
                                  get value(): number;
                                }

                                VInt.registerCustomValidator

                              static registerCustomValidator(validatorName: string, validateFunc: (value: number) => boolean): void

                              Registers a custom validator with given name. validateFunc receives a number as parameter and returns boolean based on success of validation. You must register your custom validator before using it in any of the create functions.

                                VInt.createOrThrow and VInt.tryCreate

                              static createOrThrow(validationSpec: string, value: number, varName?: string): VInt<VSpec> | never static tryCreate(validationSpec: string, value: number, varName?: string): VInt<VSpec> | never

                              Creates a new validated integer value object or throws a ValidationError exception if supplied value is invalid. validationSpec is a string of following form '[<minValue>],[<maxValue>][,<divisibleByValue>] | negative | positive | custom:<custom_validator_name>'.

                              validationSpec examples:

                                * '0,100'
                                * '0,100,2'
                                * '100,'
                                * ',0'
                                * ','
                                * 'positive'
                                * 'negative'
                                * 'custom:isEven'

                              If minValue is missing, Number.MIN_SAFE_INTEGER is used. If maxValue is missing, Number.MAX_SAFE_INTEGER is used. If varName is supplied, it is mentioned in possible ValidationError thrown.

                                VInt.create

                              static create(validationSpec: string, value: number, varName?: string): VInt<VSpec> | null

                              Same as VInt.createOrThrow, but instead of throwing on validation failure, it returns null. This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.

                                VInt.createOrError

                              static createOrError(validationSpec: string, value: number, varName?: string): [VInt<VSpec>, null] | [null, Error]

                              Same as VInt.createOrThrow, but instead of throwing on validation failure, it returns a tuple [VInt, null] on success and tuple [null, Error] on validation failure This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error. For example:

                                const [int, err] = VInt.createOrError<'1,10'>('1,10', 1);
                                if (err) {
                                  // handle error here
                                }

                                value

                              get value(): number

                              Returns the valid integer value.

                                VString

                                class VString<VSpec extends string> {
                                  static registerCustomValidator(validatorName: string | string[], validateFunc: (value: string) => boolean): void;
                                  static createOrThrow(validationSpec: string | string[], value: number, varName?: string): VString<VSpec> | never;
                                  static tryCreate(validationSpec: string | string[], value: number, varName?: string): VString<VSpec> | never;
                                  static create(validationSpec: string | string[], value: number, varName?: string): VString<VSpec> | null;
                                  static createOrError(
                                    validationSpec: string,
                                    value: number,
                                    varName?: string
                                  ): [VString<VSpec>, null] | [null, Error];
                                  get value(): string;
                                }

                                VString.registerCustomValidator

                              static registerCustomValidator(validatorName: string, validateFunc: (value: string) => boolean): void

                              Registers a custom validator with given name. validateFunc receives a string value as parameter and returns boolean based on success of validation. You must register your custom validator before using it in any of the create functions.

                                VString.createOrThrow and VString.tryCreate

                              static createOrThrow(validationSpec: string, value: number, varName?: string): VString<VSpec> | never static tryCreate(validationSpec: string, value: number, varName?: string): VString<VSpec> | never

                              Creates a new validated integer value object or throws a ValidationError exception if supplied value is invalid. validationSpec is a string of following form '[<minLength>],<maxLength>[,<unknown_length_validator_name>[,<parameter>]] | <known_length_validator_name> | custom:<custom_validator_name>'.

                              Possible value for <unknown_length_validator_name>:

                                * alpha
                                * alphanumeric
                                * ascii
                                * base32
                                * base58
                                * base64
                                * dataUri
                                * decimal
                                * fqdn
                                * md4
                                * md5
                                * sha1
                                * sha256
                                * sha384
                                * sha512
                                * crc32
                                * crc32b
                                * hex
                                * ipv4Range
                                * ipv6Range
                                * json
                                * lowercase
                                * magnetUri
                                * mongoId
                                * numeric
                                * octal
                                * uppercase
                                * strongPassword
                                * url
                                * includes (requires parameter)
                                * match (requires a RegExp string parameter)
                                * isOneOf (requires JSON string array parameter)
                                * isNoneOf (requires JSON string array parameter)
                                * startsWith (requires parameter)
                                * endsWith (requires parameter)
                                * numericRange (requires parameterin format: <minValue>-<maxValue>, e.g. 1-65535)

                              Possible values for <known_length_validator_name>:

                                * boolean
                                * bic
                                * btcAddress
                                * creditCard
                                * ean
                                * email
                                * ethereumAddress
                                * hsl
                                * hexColor
                                * isin
                                * iban
                                * ipv4
                                * ipv6
                                * iso31661Alpha2
                                * iso31661Alpha3
                                * iso8601
                                * isrc
                                * issn
                                * jwt
                                * latLong
                                * macAddress
                                * mimeType
                                * port
                                * rgbColor
                                * semVer
                                * uuid
                                * postalCode
                                * creditCardExpiration
                                * cvc
                                * mobileNumber

                              More information about validators can be found in validator.js documentation If you need a new built-in validator, please open a new issue about that.

                              validationSpec examples:

                                * '0,100'
                                * ',100'
                                * '1,1024,url'
                                * '1,1024,startsWith,https'
                                * 'email'
                                * 'custom:isSupplierName'

                              If minLength is missing, 0 is used. If varName is supplied, it is mentioned in possible ValidationError thrown.

                                VString.create

                              static create(validationSpec: string, value: number, varName?: string): VString<VSpec> | null

                              Same as VString.createOrThrow, but instead of throwing on validation failure, it returns null. This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.

                                VString.createOrError

                              static createOrError(validationSpec: string, value: number, varName?: string): [VString<VSpec>, null] | [null, Error]

                              Same as VString.createOrThrow, but instead of throwing on validation failure, it returns a tuple [VString, null] on success and tuple [null, Error] on validation failure This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error. For example:

                                const [str, err] = VString.createOrError<'1,10'>('1,10', 'abc');
                                if (err) {
                                  // handle error here
                                }

                                value

                              get value(): string

                              Returns the valid string value.

                                VArray

                              T is the type of elements in the array.

                                class VArray<VSpec extends string, T> {
                                  static registerCustomValidator(validatorName: string, validateFunc: (value: T[]) => boolean): void;
                                  static createOrThrow(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | never;
                                  static tryCreate(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | never;
                                  static create(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | null;
                                  static createOrError(
                                    validationSpec: string,
                                    value: T[],
                                    varName?: string
                                  ): [VArray<VSpec, T>, null] | [null, Error];
                                  get value(): T[];
                                }

                                VArray.registerCustomValidator

                              static registerCustomValidator(validatorName: string, validateFunc: (value: T[]) => boolean): void

                              Registers a custom validator with given name. validateFunc receives an array as parameter and returns boolean based on success of validation. You must register your custom validator before using it in any of the create functions.

                                VArray.createOrThrow and VArray.tryCreate

                              static createOrThrow(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | never static tryCreate(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | never

                              Creates a new validated array value object or throws a ValidationError exception if supplied value is invalid. validationSpec is a string of following form '[<minLength>],<maxLength>[,unique] | custom:<custom_validator_name>'.

                              validationSpec examples:

                                * '0,100'
                                * ',100'
                                * '1,10,unique'
                                * 'custom:includesSomething'

                              If minLength is missing, 0 is used. If varName is supplied, it is mentioned in possible ValidationError thrown.

                                VArray.create

                              static create(validationSpec: string, value: T[], varName?: string): VArray<VSpec, T> | null

                              Same as VFloat.createOrThrow, but instead of throwing on validation failure, it returns null. This method is useful if you don't care about the error message, but just want to know if validation succeeded or not.

                                VArray.createOrError

                              static createOrError(validationSpec: string, value: T[], varName?: string): [VArray<VSpec, T>, null] | [null, Error]

                              Same as VFloat.createOrThrow, but instead of throwing on validation failure, it returns a tuple [VArray, null] on success and tuple [null, Error] on validation failure. This method is useful for Go language style of programming where you get a 2-tuple return value where the last element in tuple contains the possible error. For example:

                                const [array, err] = VArray.createOrError<'1,10', number>('1,10', [1]);
                                if (err) {
                                  // handle error here
                                }

                                value

                              get value(): T[]

                              Returns the validated array.

                                SemType

                              T is the type of Semantic variable.

                                type SemName<N extends string> = N extends `${infer Name}` ? `${Name}` : never;
                                
                                class SemType<T, N extends string> {
                                  constructor(semanticName: SemName<N>, value: T);
                                  constructor(semType: { [K in SemName<N>]: T });
                                  get value(): T;
                                }

                                constructor

                              constructor(semanticName: SemName<N>, value: T)
                              constructor(semType: { [K in SemName<N>]: T });

                              Creates a new semantic variable with semantic name semanticName and with value of type T.

                                value

                              get value(): T Get the value of semantic variable.

                                SemVInt

                                type SemName<N extends string> = N extends `${infer Name}` ? `${Name}` : never;
                                
                                class SemVInt<Name extends string, VSpec extends string> {
                                  static tryCreate<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: IntValidationSpec<VSpec>,
                                    value: number,
                                    varName?: string
                                  ): SemVInt<Name, VSpec> | never; // Throws on error
                                
                                  static create<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: IntValidationSpec<VSpec>,
                                    value: number
                                  ): SemVInt<Name, VSpec> | null; // Returns null on error
                                
                                  static createOrError<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: IntValidationSpec<VSpec>,
                                    value: number,
                                    varName?: string
                                  ): [SemVInt<Name, VSpec>, null] | [null, Error] // Returns a pair [null, Error] on error
                                }

                                SemVFloat

                                type SemName<N extends string> = N extends `${infer Name}` ? `${Name}` : never;
                                
                                class SemVFloat<Name extends string, VSpec extends string> {
                                  static tryCreate<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: FloatValidationSpec<VSpec>,
                                    value: number,
                                    varName?: string
                                  ): SemVFloat<Name, VSpec> | never; // Throws on error
                                
                                  static create<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: FloatValidationSpec<VSpec>,
                                    value: number
                                  ): SemVFloat<Name, VSpec> | null // Returns null on error
                                
                                  static createOrError<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: FloatValidationSpec<VSpec>,
                                    value: number,
                                    varName?: string
                                  ): [SemVFloat<Name, VSpec>, null] | [null, Error]; // Returns a pair [null, Error] on error
                                }

                                SemVString

                                type SemName<N extends string> = N extends `${infer Name}` ? `${Name}` : never;
                                
                                class SemVString<Name extends string, VSpec extends string | string[]> {
                                  static tryCreate<Name extends string, VSpec extends string | string[]>(
                                    semanticName: SemName<Name>,
                                    validationSpec: string | string[],
                                    value: string,
                                    varName?: string
                                  ): SemVString<Name, VSpec> | never; // Throws on error
                                
                                  static create<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: string | string[],
                                    value: string,
                                    varName?: string
                                  ): SemVString<Name, VSpec> | null; // Returns null on error
                                
                                  static createOrError<Name extends string, VSpec extends string>(
                                    semanticName: SemName<Name>,
                                    validationSpec: string | string[],
                                    value: string,
                                    varName?: string
                                  ): [SemVString<Name, VSpec>, null] | [null, Error]; // Returns a pair [null, Error] on error
                                }

                                VSpecOf

                              Extracts the validation spec type of the validated type.

                              For example:

                                type Month = VInt<'1,12'>;
                                const monthVSpec: VSpecOf<Month> = '1,12';
                                const month: Month = VInt.tryCreate(monthVSpec, 1);
                                
                                type Percent = VFloat<'0,100'>;
                                const percentVSpec: VSpecOf<Percent> = '0,100';
                                const percent: Percent = VFloat.tryCreate(percentVSpec, 25.0);
                                
                                type Url = VString<['1,1024,lowercase', 'url', 'startsWith,https', 'endsWith,.html']>;
                                const urlVSpec: VSpecOf<Url> = ['1,1024,lowercase', 'url', 'startsWith,https', 'endsWith,.html'];
                                const url: Url = VString.tryCreate(urlVSpec, 'https://server.domain.com:8080/index.html');

                                Feedback

                              If you want to report a bug, please create a new issue about that.

                              If you want to request a new feature, for example, a new type of validator for string, please create a new issue about that.

                                License

                              MIT

                          About

                          Library for creating validated Typescript types for integers, floats, string and arrays

                          Topics

                              node typescript validation type

                          Resources

                            Readme

                          License

                            MIT license
                            Activity

                          Stars

                            18 stars

                          Watchers

                            1 watching

                          Forks

                            3 forks
                            Report repository

                        Releases

                          No releases published

                        Packages 0

                          No packages published

                        Languages

                          * TypeScript 99.9%
                          * Shell 0.1%

    Footer

        © 2024 GitHub, Inc.

      Footer navigation

        * Terms
        * Privacy
        * Security
        * Status
        * Docs
        * Contact
        * Manage cookies
        * Do not share my personal information
      You can’t perform that action at this time.
GitHub - pksilen/validated-types: Library for creating validated Typescript types for integers, floats, string and arrays
https://github.com/pksilen/validated-types
jcoreio
2020-07-12T02:22:59Z
<div><div><article><p></p><h2>typescript-validators</h2><a href="#typescript-validators"></a><p></p>
<p><a href="https://circleci.com/gh/jcoreio/typescript-validators"></a>
<a href="https://codecov.io/gh/jcoreio/typescript-validators"></a>
<a href="https://github.com/semantic-release/semantic-release"></a>
<a href="http://commitizen.github.io/cz-cli/"></a>
<a href="https://badge.fury.io/js/typescript-validators"></a></p>
<p>Complex type validators that generate TypeScript types for you.
The validation errors are detailed. Adapted from the brilliant work in <code>flow-runtime</code>.</p>
<p></p><h2>Deprecated</h2><a href="#deprecated"></a><p></p>
<p>I recreated this project as <a href="https://github.com/jcoreio/typed-validators"><code>typed-validators</code></a> and added Flow support!</p>
<p>A few breaking changes to the API were necessary for Flow support, but they also made it easier to declare objects with
optional properties.</p>
<p></p><h2>Table of Contents</h2><a href="#table-of-contents"></a><p></p>

<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#what-about-generating-validators-from-type-defs">What about generating validators from type defs?</a></li>
<li><a href="#api">API</a>
<ul>
<li><a href="#type-creators">Type creators</a>
<ul>
<li><a href="#tboolean"><code>t.boolean()</code></a></li>
<li><a href="#tbooleantrue"><code>t.boolean(true)</code></a></li>
<li><a href="#tstring"><code>t.string()</code></a></li>
<li><a href="#tstringfoo"><code>t.string('foo')</code></a></li>
<li><a href="#tnumber"><code>t.number()</code></a></li>
<li><a href="#tnumber3"><code>t.number(3)</code></a></li>
<li><a href="#tsymbol"><code>t.symbol()</code></a></li>
<li><a href="#tsymbolmysymbol"><code>t.symbol(MySymbol)</code></a></li>
<li><a href="#tnull--tnullliteral"><code>t.null()</code> / <code>t.nullLiteral()</code></a></li>
<li><a href="#tnullortstring"><code>t.nullOr(t.string())</code></a></li>
<li><a href="#tundefined--tundefinedliteral"><code>t.undefined()</code> / <code>t.undefinedLiteral()</code></a></li>
<li><a href="#tnullish"><code>t.nullish()</code></a></li>
<li><a href="#tnullishortstring"><code>t.nullishOr(t.string())</code></a></li>
<li><a href="#tarraytnumber"><code>t.array(t.number())</code></a></li>
<li><a href="#tsimpleobject-foo-tstring-"><code>t.simpleObject({ foo: t.string() })</code></a></li>
<li><a href="#tobject"><code>t.object</code></a></li>
<li><a href="#trecordtstring-tnumber"><code>t.record(t.string(), t.number())</code></a></li>
<li><a href="#tinstanceofdate"><code>t.instanceOf(Date)</code></a></li>
<li><a href="#ttupletstring-tnumber"><code>t.tuple(t.string(), t.number())</code></a></li>
<li><a href="#tallofa-b"><code>t.allOf(A, B)</code></a></li>
<li><a href="#toneoftstring-tnumber"><code>t.oneOf(t.string(), t.number())</code></a></li>
<li><a href="#taliasname-type"><code>t.alias(name, type)</code></a></li>
<li><a href="#tref--typealias"><code>t.ref(() =&gt; typeAlias)</code></a></li>
</ul>
</li>
<li><a href="#ttypet"><code>t.Type&lt;T&gt;</code></a>
<ul>
<li><a href="#acceptsinput-any-boolean"><code>accepts(input: any): boolean</code></a></li>
<li><a href="#assertv-extends-tinput-any-prefix---path-string--number--symbol-v"><code>assert&lt;V extends T&gt;(input: any, prefix = '', path?: (string | number | symbol)[]): V</code></a></li>
<li><a href="#validateinput-any-prefix---path-string--number--symbol-validationt"><code>validate(input: any, prefix = '', path?: (string | number | symbol)[]): Validation&lt;T&gt;</code></a></li>
<li><a href="#tostring-string"><code>toString(): string</code></a></li>
</ul>
</li>
<li><a href="#textracttypet-extends-typeany"><code>t.ExtractType&lt;T extends Type&lt;any&gt;&gt;</code></a></li>
<li><a href="#ttypealiast"><code>t.TypeAlias&lt;T&gt;</code></a>
<ul>
<li><a href="#readonly-name-string"><code>readonly name: string</code></a></li>
<li><a href="#addconstraintconstraints-typeconstraintt-this"><code>addConstraint(...constraints: TypeConstraint&lt;T&gt;[]): this</code></a></li>
</ul>
</li>
<li><a href="#custom-constraints">Custom Constraints</a></li>
<li><a href="#recursive-types">Recursive Types</a></li>
</ul>
</li>
</ul>

<p></p><h2>Introduction</h2><a href="#introduction"></a><p></p>
<p>When you need to validate the inputs to a TypeScript API, a problem arises. How do you ensure that a value that passes validation
matches your declared TypeScript type? Someone might modify one and forget to modify the other:</p>
<div><pre><span>type</span> <span>Post</span> <span>=</span> <span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>string</span>
    <span>username</span>: <span>string</span>
  <span>}</span>
  <span>content</span>: <span>string</span>
  <span>// newly added by developer</span>
  <span>tags</span>: <span>string</span><span>[</span><span>]</span>
<span>}</span>

<span>// hypothetical syntax</span>
<span>const</span> <span>validator</span> <span>=</span> <span>requireObject</span><span>(</span><span>{</span>
  <span>author</span>: <span>requireObject</span><span>(</span><span>{</span>
    <span>name</span>: <span>requireString</span><span>(</span><span>)</span><span>,</span>
    <span>username</span>: <span>requireString</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span>
  <span>content</span>: <span>requireString</span><span>(</span><span>)</span><span>,</span>
  <span>// uhoh!! developer forgot to add tags here</span>
<span>}</span><span>)</span></pre></div>
<p><code>typescript-validators</code> solves this by generating TypeScript types from your validators:</p>
<div><pre><span>import</span> <span>*</span> <span>as</span> <span>t</span> <span>from</span> <span>'typescript-validators'</span>

<span>const</span> <span>PostValidator</span> <span>=</span> <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span>
  <span>author</span>: <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span>
    <span>name</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    <span>username</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span>
  <span>content</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>tags</span>: <span>t</span><span>.</span><span>array</span><span>(</span><span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span>

<span>type</span> <span>Post</span> <span>=</span> <span>t</span><span>.</span><span>ExtractType</span><span>&lt;</span><span>typeof</span> <span>PostValidator</span><span>&gt;</span>

<span>const</span> <span>example</span>: <span>Post</span> <span>=</span> <span>PostValidator</span><span>.</span><span>assert</span><span>(</span><span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>'MC Hammer'</span><span>,</span>
    <span>username</span>: <span>'hammertime'</span><span>,</span>
  <span>}</span><span>,</span>
  <span>content</span>: <span>"Can't touch this"</span><span>,</span>
  <span>tags</span>: <span>[</span><span>'mc-hammer'</span><span>,</span> <span>'hammertime'</span><span>]</span><span>,</span>
<span>}</span><span>)</span></pre></div>
<p>Hover over <code>Post</code> in VSCode and you'll see, voilà:</p>
<div><pre><span>type</span> <span>Post</span> <span>=</span> <span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>string</span>
    <span>username</span>: <span>string</span>
  <span>}</span>
  <span>content</span>: <span>string</span>
  <span>tags</span>: <span>string</span><span>[</span><span>]</span>
<span>}</span></pre></div>
<p></p><h2>What about generating validators from type defs?</h2><a href="#what-about-generating-validators-from-type-defs"></a><p></p>
<p>I'd like to be able to do this, because type defs are a lot more readable. In fact, for Flow, it's possible with
<code>babel-pluging-flow-runtime</code>, which I have a lot of experience with. That looks like this:</p>
<div><pre><span>import</span> <span>{</span><span>type</span> <span>Type</span><span>,</span> <span>reify</span><span>}</span> <span>from</span> <span>'flow-runtime'</span>

<span>type</span> <span>Post</span> <span>=</span> <span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>string</span>
    <span>username</span>: <span>string</span>
  <span>}</span>
  <span>content</span>: <span>string</span>
  <span>tags</span>: <span>string</span><span>[</span><span>]</span>
<span>}</span>

<span>const</span> <span>PostValidator</span> <span>=</span> <span>(</span><span>reify</span>: <span>Type</span><span>&lt;</span><span>Post</span><span>&gt;</span><span></span><span>)</span> <span>// looooots of magic here</span>

<span>const</span> <span>example</span>: <span>Post</span> <span>=</span> <span>PostValidator</span><span>.</span><span>assert</span><span>(</span><span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>'MC Hammer'</span><span>,</span>
    <span>username</span>: <span>'hammertime'</span><span>,</span>
  <span>}</span><span>,</span>
  <span>content</span>: <span>"Can't touch this"</span><span>,</span>
  <span>tags</span>: <span>[</span><span>'mc-hammer'</span><span>,</span> <span>'hammertime'</span><span>]</span><span>,</span>
<span>}</span><span>)</span></pre></div>
<p>This is sweet but there are some caveats:</p>
<ul>
<li>You have to add a Babel plugin to your toolchain (for TypeScript, not everyone wants to use Babel)</li>
<li>There are issues with the Babel plugin. It aims to support all Flow types, with varying success.</li>
<li>The original author of <code>flow-runtime</code> abandoned the project and I don't blame him. It was hugely ambitious and difficult to maintain.</li>
</ul>
<p>The author of <code>flow-runtime</code> himself told me in private conversations that he had moved on to an approach like
<code>typescript-validators</code> in his own projects, because generating types from the validator declarations is a lot
simpler and more maintainable in the long run.</p>
<p></p><h2>API</h2><a href="#api"></a><p></p>
<p>I recommend importing like this:</p>
<div><pre><span>import</span> <span>*</span> <span>as</span> <span>t</span> <span>from</span> <span>'typescript-validators'</span></pre></div>
<p></p><h2>Type creators</h2><a href="#type-creators"></a><p></p>
<p>All of the following methods return an instance of <code>t.Type&lt;T&gt;</code>.</p>
<p></p><h3><code>t.boolean()</code></h3><a href="#tboolean"></a><p></p>
<p>A validator that requires the value to be a <code>boolean</code>.</p>
<p></p><h3><code>t.boolean(true)</code></h3><a href="#tbooleantrue"></a><p></p>
<p>A validator that requires the value to be <code>true</code>.</p>
<p></p><h3><code>t.string()</code></h3><a href="#tstring"></a><p></p>
<p>A validator that requires the value to be a <code>string</code>.</p>
<p></p><h3><code>t.string('foo')</code></h3><a href="#tstringfoo"></a><p></p>
<p>A validator that requires the value to be <code>'foo'</code>.</p>
<p></p><h3><code>t.number()</code></h3><a href="#tnumber"></a><p></p>
<p>A validator that requires the value to be a <code>number</code>.</p>
<p></p><h3><code>t.number(3)</code></h3><a href="#tnumber3"></a><p></p>
<p>A validator that requires the value to be <code>3</code>.</p>
<p></p><h3><code>t.symbol()</code></h3><a href="#tsymbol"></a><p></p>
<p>A validator that requires the value to be a <code>symbol</code>.</p>
<p></p><h3><code>t.symbol(MySymbol)</code></h3><a href="#tsymbolmysymbol"></a><p></p>
<p>A validator that requires the value to be <code>MySymbol</code>.</p>
<p></p><h3><code>t.null()</code> / <code>t.nullLiteral()</code></h3><a href="#tnull--tnullliteral"></a><p></p>
<p>A validator that requires the value to be <code>null</code>.</p>
<p></p><h3><code>t.nullOr(t.string())</code></h3><a href="#tnullortstring"></a><p></p>
<p>A validator that requires the value to be <code>string | null</code></p>
<p></p><h3><code>t.undefined()</code> / <code>t.undefinedLiteral()</code></h3><a href="#tundefined--tundefinedliteral"></a><p></p>
<p>A validator that requires the value to be <code>undefined</code>.</p>
<p></p><h3><code>t.nullish()</code></h3><a href="#tnullish"></a><p></p>
<p>A validator that requires the value to be <code>null | undefined</code>.</p>
<p></p><h3><code>t.nullishOr(t.string())</code></h3><a href="#tnullishortstring"></a><p></p>
<p>A validator that requires the value to be <code>string | null | undefined</code>.</p>
<p></p><h3><code>t.array(t.number())</code></h3><a href="#tarraytnumber"></a><p></p>
<p>A validator that requires the value to be <code>number[]</code>.</p>
<p></p><h3><code>t.simpleObject({ foo: t.string() })</code></h3><a href="#tsimpleobject-foo-tstring-"></a><p></p>
<p>A validator that requires the value to be an object with only a <code>foo</code> property that's a <code>string</code>.</p>
<p></p><h3><code>t.object</code></h3><a href="#tobject"></a><p></p>
<p>For dealing with optional properties, use the following.
The syntax is a bit awkward but it's the best way I could find to get a clean type output:</p>
<div><pre><span>const</span> <span>ThingValidator</span> <span>=</span> <span>t</span><span>.</span><span>object</span><span>&lt;</span><span>{</span>
  <span>name</span>: <span>any</span>
  <span>comment</span>?: <span>any</span>
<span>}</span><span>&gt;</span><span>(</span><span>)</span><span>(</span><span>{</span>
  <span>name</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>comment</span>: <span>t</span><span>.</span><span>optional</span><span>(</span><span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span>

<span>type</span> <span>Thing</span> <span>=</span> <span>t</span><span>.</span><span>ExtractType</span><span>&lt;</span><span>typeof</span> <span>ThingValidator</span><span>&gt;</span></pre></div>
<p>The type of <code>Thing</code> will be <code>{ name: string, comment?: string }</code>. Note that the property types in the explicit type parameter
(<code>any</code>) are ignored. The type parameter just indicates which properties are required and which are optional, and also allows
you to mark properties readonly. These attributes will be reflected in <code>t.ExtractType</code>.</p>
<p>You can also use the <code>t.optionalNullOr(t.string())</code> as a shorthand for
<code>t.optional(t.nullOr(t.string()))</code>.</p>
<p></p><h3><code>t.record(t.string(), t.number())</code></h3><a href="#trecordtstring-tnumber"></a><p></p>
<p>A validator that requires the value to be <code>Record&lt;string, number&gt;</code>.</p>
<p></p><h3><code>t.instanceOf(Date)</code></h3><a href="#tinstanceofdate"></a><p></p>
<p>A validator that requires the value to be an instance of <code>Date</code>.</p>
<p></p><h3><code>t.tuple(t.string(), t.number())</code></h3><a href="#ttupletstring-tnumber"></a><p></p>
<p>A validator that requires the value to be <code>[string, number]</code>.
Accepts a variable number of arguments.</p>
<p></p><h3><code>t.allOf(A, B)</code></h3><a href="#tallofa-b"></a><p></p>
<p>A validator that requires the value to be <code>A &amp; B</code>. Accepts a variable number of arguments, though type generation is only overloaded up to 8 arguments. For example:</p>
<div><pre><span>const</span> <span>ThingType</span> <span>=</span> <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span> <span>name</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span>
<span>const</span> <span>CommentedType</span> <span>=</span> <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span> <span>comment</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span> <span>}</span><span>)</span>

<span>const</span> <span>CommentedThingType</span> <span>=</span> <span>t</span><span>.</span><span>allOf</span><span>(</span><span>ThingType</span><span>,</span> <span>CommentedType</span><span>)</span>

<span>CommentedThingType</span><span>.</span><span>assert</span><span>(</span><span>{</span> <span>name</span>: <span>'foo'</span><span>,</span> <span>comment</span>: <span>'sweet'</span> <span>}</span><span>)</span></pre></div>
<p></p><h3><code>t.oneOf(t.string(), t.number())</code></h3><a href="#toneoftstring-tnumber"></a><p></p>
<p>A validator that requires the value to be <code>string | number</code>. Accepts a variable number of arguments, though type generation is only overloaded up to 8 arguments.</p>
<p></p><h3><code>t.alias(name, type)</code></h3><a href="#taliasname-type"></a><p></p>
<p>Creates a <code>TypeAlias</code> with the given <code>name</code> and <code>type</code>.</p>
<p>Type aliases serve two purposes:</p>
<ul>
<li>They allow you to <a href="#recursive-types">create recursive type validators with <code>t.ref()</code></a></li>
<li>You can <a href="#custom-constraints">add custom constraints to them</a></li>
</ul>
<p></p><h3><code>t.ref(() =&gt; typeAlias)</code></h3><a href="#tref--typealias"></a><p></p>
<p>Creates a reference to the given <code>TypeAlias</code>. See <a href="#recursive-types">Recursive Types</a> for examples.</p>
<p></p><h2><code>t.Type&lt;T&gt;</code></h2><a href="#ttypet"></a><p></p>
<p>The base class for all validator types.</p>
<p><code>T</code> is the type of values it accepts.</p>
<p></p><h3><code>accepts(input: any): boolean</code></h3><a href="#acceptsinput-any-boolean"></a><p></p>
<p>Returns <code>true</code> if and only if <code>input</code> is the correct type.</p>
<p></p><h3><code>assert&lt;V extends T&gt;(input: any, prefix = '', path?: (string | number | symbol)[]): V</code></h3><a href="#assertv-extends-tinput-any-prefix---path-string--number--symbol-v"></a><p></p>
<p>Throws an error if <code>input</code> isn't the correct type.</p>
<p><code>prefix</code> will be prepended to thrown error messages.</p>
<p><code>path</code> will be prepended to validation error paths. If you are validating a function parameter named <code>foo</code>,
pass <code>['foo']</code> for <code>path</code> to get clear error messages.</p>
<p></p><h3><code>validate(input: any, prefix = '', path?: (string | number | symbol)[]): Validation&lt;T&gt;</code></h3><a href="#validateinput-any-prefix---path-string--number--symbol-validationt"></a><p></p>
<p>Validates <code>input</code>, returning any errors in the <code>Validation</code>.</p>
<p><code>prefix</code> and <code>path</code> are the same as in <code>assert</code>.</p>
<p></p><h3><code>warn(input: any, prefix = '', path?: (string | number | symbol)[]): void</code></h3><a href="#warninput-any-prefix---path-string--number--symbol-void"></a><p></p>
<p>Logs a warning to the console if <code>input</code> isn't the correct type.</p>
<p></p><h3><code>toString(): string</code></h3><a href="#tostring-string"></a><p></p>
<p>Returns a string representation of this type (using TS type syntax in most cases).</p>
<p></p><h2><code>t.ExtractType&lt;T extends Type&lt;any&gt;&gt;</code></h2><a href="#textracttypet-extends-typeany"></a><p></p>
<p>Gets the TypeScript type that a validator type accepts. For example:</p>
<div><pre><span>import</span> <span>*</span> <span>as</span> <span>t</span> <span>from</span> <span>'typescript-validators'</span>

<span>const</span> <span>PostValidator</span> <span>=</span> <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span>
  <span>author</span>: <span>t</span><span>.</span><span>simpleObject</span><span>(</span><span>{</span>
    <span>name</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
    <span>username</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>}</span><span>)</span><span>,</span>
  <span>content</span>: <span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>,</span>
  <span>tags</span>: <span>t</span><span>.</span><span>array</span><span>(</span><span>t</span><span>.</span><span>string</span><span>(</span><span>)</span><span>)</span><span>,</span>
<span>}</span><span>)</span>

<span>type</span> <span>Post</span> <span>=</span> <span>t</span><span>.</span><span>ExtractType</span><span>&lt;</span><span>typeof</span> <span>PostValidator</span><span>&gt;</span></pre></div>
<p>Hover over <code>Post</code> in the IDE and you'll see, voilà:</p>
<div><pre><span>type</span> <span>Post</span> <span>=</span> <span>{</span>
  <span>author</span>: <span>{</span>
    <span>name</span>: <span>string</span>
    <span>username</span>: <span>string</span>
  <span>}</span>
  <span>content</span>: <span>string</span>
  <span>tags</span>: <span>string</span><span>[</span><span>]</span>
<span>}</span></pre></div>
<p></p><h2><code>t.TypeAlias&lt;T&gt;</code></h2><a href="#ttypealiast"></a><p></p>
<p></p><h3><code>readonly name: string</code></h3><a href="#readonly-name-string"></a><p></p>
<p>The name of the alias.</p>
<p></p><h3><code>addConstraint(...constraints: TypeConstraint&lt;T&gt;[]): this</code></h3><a href="#addconstraintconstraints-typeconstraintt-this"></a><p></p>
<p>Adds custom constraints. <code>TypeConstraint&lt;T&gt;</code> is a function <code>(value: T) =&gt; string | null | undefined</code> which
returns nullish if <code>value</code> is valid, or otherwise a <code>string</code> describing why <code>value</code> is invalid.</p>
<p></p><h2>Custom Constraints</h2><a href="#custom-constraints"></a><p></p>
<p>It's nice to be able to validate that something is a <code>number</code>, but what if we want to make sure it's positive?
We can do this by creating a type alias for <code>number</code> and adding a custom constraint to it:</p>
<div><pre><span>const</span> <span>PositiveNumberType</span> <span>=</span> <span>t</span>
  <span>.</span><span>alias</span><span>(</span><span>'PositiveNumber'</span><span>,</span> <span>t</span><span>.</span><span>number</span><span>(</span><span>)</span><span>)</span>
  <span>.</span><span>addConstraint</span><span>(</span><span>(</span><span>value</span>: <span>number</span><span>)</span> <span>=&gt;</span> <span>(</span><span>value</span> <span>&gt;</span> <span>0</span> ? <span>undefined</span> : <span>'must be &gt; 0'</span><span>)</span><span>)</span>

<span>PositiveNumberType</span><span>.</span><span>assert</span><span>(</span><span>-</span><span>1</span><span>)</span></pre></div>
<p>The assertion will throw a <code>t.RuntimeTypeError</code> with the following message:</p>
<div><pre><code>Value must be &gt; 0

Expected: PositiveNumber

Actual Value: -1

Actual Type: number
</code></pre></div>
<p></p><h2>Recursive Types</h2><a href="#recursive-types"></a><p></p>
<p>Creating validators for recursive types takes a bit of extra effort. Naively, we would want to do this:</p>
<div><pre><span>const</span> <span>NodeType</span> <span>=</span> <span>t</span><span>.</span><span>object</span><span>&lt;</span><span>{</span>
  <span>value</span>: <span>any</span>
  <span>left</span>?: <span>any</span>
  <span>right</span>?: <span>any</span>
<span>}</span><span>&gt;</span><span>(</span><span>)</span><span>(</span><span>{</span>
  <span>value</span>: <span>t</span><span>.</span><span>any</span><span>(</span><span>)</span><span>,</span>
  <span>left</span>: <span>t</span><span>.</span><span>optional</span><span>(</span><span>NodeType</span><span>)</span><span>,</span>
  <span>right</span>: <span>t</span><span>.</span><span>optional</span><span>(</span><span>NodeType</span><span>)</span><span>,</span>
<span>}</span><span>)</span></pre></div>
<p>But <code>t.optional(NodeType)</code> causes the error <code>Block-scoped variable 'NodeType' referenced before its declaration</code>.</p>
<p>To work around this, we can create a <code>TypeAlias</code> and a reference to it:</p>
<div><pre><span>const</span> <span>NodeType</span>: <span>t</span><span>.</span><span>TypeAlias</span><span>&lt;</span><span>{</span>
  <span>value</span>: <span>any</span>
  <span>left</span>?: <span>Node</span>
  <span>right</span>?: <span>Node</span>
<span>}</span><span>&gt;</span> <span>=</span> <span>t</span><span>.</span><span>alias</span><span>(</span>
  <span>'Node'</span><span>,</span>
  <span>t</span><span>.</span><span>object</span><span>&lt;</span><span>{</span>
    <span>value</span>: <span>any</span>
    <span>left</span>?: <span>any</span>
    <span>right</span>?: <span>any</span>
  <span>}</span><span>&gt;</span><span>(</span><span>)</span><span>(</span><span>{</span>
    <span>value</span>: <span>t</span><span>.</span><span>any</span><span>(</span><span>)</span><span>,</span>
    <span>left</span>: <span>t</span><span>.</span><span>optional</span><span>(</span><span>t</span><span>.</span><span>ref</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>NodeType</span><span>)</span><span>)</span><span>,</span>
    <span>right</span>: <span>t</span><span>.</span><span>optional</span><span>(</span><span>t</span><span>.</span><span>ref</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>NodeType</span><span>)</span><span>)</span><span>,</span>
  <span>}</span><span>)</span>
<span>)</span>

<span>type</span> <span>Node</span> <span>=</span> <span>t</span><span>.</span><span>ExtractType</span><span>&lt;</span><span>typeof</span> <span>NodeType</span><span>&gt;</span>

<span>NodeType</span><span>.</span><span>assert</span><span>(</span><span>{</span>
  <span>value</span>: <span>'foo'</span><span>,</span>
  <span>left</span>: <span>{</span>
    <span>value</span>: <span>2</span><span>,</span>
    <span>right</span>: <span>{</span>
      <span>value</span>: <span>3</span><span>,</span>
    <span>}</span><span>,</span>
  <span>}</span><span>,</span>
  <span>right</span>: <span>{</span>
    <span>value</span>: <span>6</span><span>,</span>
  <span>}</span><span>,</span>
<span>}</span><span>)</span></pre></div>
<p>Notice how we use a thunk function in <code>t.ref(() =&gt; NodeType)</code> to avoid referencing <code>NodeType</code> before its declaration.</p>
</article></div></div>||||I||||    Skip to content

    Navigation Menu

    Toggle navigation
          Sign in
            * Product
                        + Actions
                        Automate any workflow
                        + Packages
                        Host and manage packages
                        + Security
                        Find and fix vulnerabilities
                        + Codespaces
                        Instant dev environments
                        + GitHub Copilot
                        Write better code with AI
                        + Code review
                        Manage code changes
                        + Issues
                        Plan and track work
                        + Discussions
                        Collaborate outside of code
                  Explore
                    + All features
                    + Documentation
                    + GitHub Skills
                    + Blog
            * Solutions
                  By size
                    + Enterprise
                    + Teams
                    + Startups
                  By industry
                    + Healthcare
                    + Financial services
                    + Manufacturing
                  By use case
                    + CI/CD & Automation
                    + DevOps
                    + DevSecOps
            * Resources
                  Topics
                    + AI
                    + DevOps
                    + Security
                    + Software Development
                  Explore
                    + Learning Pathways
                    + White papers, Ebooks, Webinars
                    + Customer Stories
                    + Partners
            * Open Source
                        + GitHub Sponsors
                        Fund open source developers
                        + The ReadME Project
                        GitHub community articles
                  Repositories
                    + Topics
                    + Trending
                    + Collections
            * Enterprise
                        + Enterprise platform
                        AI-powered developer platform
                  Available add-ons
                        + Advanced Security
                        Enterprise-grade security features
                        + GitHub Copilot
                        Enterprise-grade AI features
                        + Premium Support
                        Enterprise-grade 24/7 support
            * Pricing
              Search or jump to...

                Search code, repositories, users, issues, pull requests...

                        Search
                          Clear
                        Search syntax tips

                    Provide feedback

                We read every piece of feedback, and take your input very seriously.

                Include my email address so I can be contacted
                Cancel Submit feedback

                    Saved searches

                    Use saved searches to filter your results more quickly

                    Name
                    Query

                  To see all available qualifiers, see our documentation.

                Cancel Create saved search
              Sign in
            Sign up Reseting focus
      You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert
            {{ message }}
              jcoreio / typescript-validators Public
              * Notifications You must be signed in to change notification settings
              * Fork 1
                * Star 12

            API input validators with user-friendly error output and TypeScript to ensure you don't miss any properties

            License

              MIT license
              12 stars 1 fork Branches Tags Activity
                  Star
                Notifications You must be signed in to change notification settings
          * Code
          * Issues 0
          * Pull requests 21
          * Actions
          * Projects 0
          * Security
          * Insights
          Additional navigation options
                  * Code
                  * Issues
                  * Pull requests
                  * Actions
                  * Projects
                  * Security
                  * Insights

        jcoreio/typescript-validators

                  This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
                              master
                          Branches Tags
                            Go to file
                        Code

                        Folders and files

                          Name                   Name                     Last commit message    Last commit date
                            Latest commit      
                                               
                                History        
                                               
                                40 Commits     
                                  .circleci              .circleci                                               
                                  src                    src                                                     
                                  test                   test                                                    
                                  .babelrc.js            .babelrc.js                                             
                                  .eslintrc              .eslintrc                                               
                                  .gitignore             .gitignore                                              
                                  .npmignore             .npmignore                                              
                                  LICENSE.md             LICENSE.md                                              
                                  README.md              README.md                                               
                                  package.json           package.json                                            
                                  tsconfig.json          tsconfig.json                                           
                                  yarn.lock              yarn.lock                                               
                            View all files     
                          

                              Repository files navigation

                                * README
                                * MIT license

                                typescript-validators

                              Complex type validators that generate TypeScript types for you. The validation errors are detailed. Adapted from the brilliant work in flow-runtime.

                                Deprecated

                              I recreated this project as typed-validators and added Flow support!

                              A few breaking changes to the API were necessary for Flow support, but they also made it easier to declare objects with optional properties.

                                Table of Contents

                                * Introduction
                                * What about generating validators from type defs?
                                * API
                                    + Type creators
                                        o t.boolean()
                                        o t.boolean(true)
                                        o t.string()
                                        o t.string('foo')
                                        o t.number()
                                        o t.number(3)
                                        o t.symbol()
                                        o t.symbol(MySymbol)
                                        o t.null() / t.nullLiteral()
                                        o t.nullOr(t.string())
                                        o t.undefined() / t.undefinedLiteral()
                                        o t.nullish()
                                        o t.nullishOr(t.string())
                                        o t.array(t.number())
                                        o t.simpleObject({ foo: t.string() })
                                        o t.object
                                        o t.record(t.string(), t.number())
                                        o t.instanceOf(Date)
                                        o t.tuple(t.string(), t.number())
                                        o t.allOf(A, B)
                                        o t.oneOf(t.string(), t.number())
                                        o t.alias(name, type)
                                        o t.ref(() => typeAlias)
                                    + t.Type<T>
                                        o accepts(input: any): boolean
                                        o assert<V extends T>(input: any, prefix = '', path?: (string | number | symbol)[]): V
                                        o validate(input: any, prefix = '', path?: (string | number | symbol)[]): Validation<T>
                                        o toString(): string
                                    + t.ExtractType<T extends Type<any>>
                                    + t.TypeAlias<T>
                                        o readonly name: string
                                        o addConstraint(...constraints: TypeConstraint<T>[]): this
                                    + Custom Constraints
                                    + Recursive Types

                                Introduction

                              When you need to validate the inputs to a TypeScript API, a problem arises. How do you ensure that a value that passes validation matches your declared TypeScript type? Someone might modify one and forget to modify the other:

                                type Post = {
                                  author: {
                                    name: string
                                    username: string
                                  }
                                  content: string
                                  // newly added by developer
                                  tags: string[]
                                }
                                
                                // hypothetical syntax
                                const validator = requireObject({
                                  author: requireObject({
                                    name: requireString(),
                                    username: requireString(),
                                  }),
                                  content: requireString(),
                                  // uhoh!! developer forgot to add tags here
                                })

                              typescript-validators solves this by generating TypeScript types from your validators:

                                import * as t from 'typescript-validators'
                                
                                const PostValidator = t.simpleObject({
                                  author: t.simpleObject({
                                    name: t.string(),
                                    username: t.string(),
                                  }),
                                  content: t.string(),
                                  tags: t.array(t.string()),
                                })
                                
                                type Post = t.ExtractType<typeof PostValidator>
                                
                                const example: Post = PostValidator.assert({
                                  author: {
                                    name: 'MC Hammer',
                                    username: 'hammertime',
                                  },
                                  content: "Can't touch this",
                                  tags: ['mc-hammer', 'hammertime'],
                                })

                              Hover over Post in VSCode and you'll see, voilà:

                                type Post = {
                                  author: {
                                    name: string
                                    username: string
                                  }
                                  content: string
                                  tags: string[]
                                }

                                What about generating validators from type defs?

                              I'd like to be able to do this, because type defs are a lot more readable. In fact, for Flow, it's possible with babel-pluging-flow-runtime, which I have a lot of experience with. That looks like this:

                                import {type Type, reify} from 'flow-runtime'
                                
                                type Post = {
                                  author: {
                                    name: string
                                    username: string
                                  }
                                  content: string
                                  tags: string[]
                                }
                                
                                const PostValidator = (reify: Type<Post>) // looooots of magic here
                                
                                const example: Post = PostValidator.assert({
                                  author: {
                                    name: 'MC Hammer',
                                    username: 'hammertime',
                                  },
                                  content: "Can't touch this",
                                  tags: ['mc-hammer', 'hammertime'],
                                })

                              This is sweet but there are some caveats:

                                * You have to add a Babel plugin to your toolchain (for TypeScript, not everyone wants to use Babel)
                                * There are issues with the Babel plugin. It aims to support all Flow types, with varying success.
                                * The original author of flow-runtime abandoned the project and I don't blame him. It was hugely ambitious and difficult to maintain.

                              The author of flow-runtime himself told me in private conversations that he had moved on to an approach like typescript-validators in his own projects, because generating types from the validator declarations is a lot simpler and more maintainable in the long run.

                                API

                              I recommend importing like this:

                                import * as t from 'typescript-validators'

                                Type creators

                              All of the following methods return an instance of t.Type<T>.

                                t.boolean()

                              A validator that requires the value to be a boolean.

                                t.boolean(true)

                              A validator that requires the value to be true.

                                t.string()

                              A validator that requires the value to be a string.

                                t.string('foo')

                              A validator that requires the value to be 'foo'.

                                t.number()

                              A validator that requires the value to be a number.

                                t.number(3)

                              A validator that requires the value to be 3.

                                t.symbol()

                              A validator that requires the value to be a symbol.

                                t.symbol(MySymbol)

                              A validator that requires the value to be MySymbol.

                                t.null() / t.nullLiteral()

                              A validator that requires the value to be null.

                                t.nullOr(t.string())

                              A validator that requires the value to be string | null

                                t.undefined() / t.undefinedLiteral()

                              A validator that requires the value to be undefined.

                                t.nullish()

                              A validator that requires the value to be null | undefined.

                                t.nullishOr(t.string())

                              A validator that requires the value to be string | null | undefined.

                                t.array(t.number())

                              A validator that requires the value to be number[].

                                t.simpleObject({ foo: t.string() })

                              A validator that requires the value to be an object with only a foo property that's a string.

                                t.object

                              For dealing with optional properties, use the following. The syntax is a bit awkward but it's the best way I could find to get a clean type output:

                                const ThingValidator = t.object<{
                                  name: any
                                  comment?: any
                                }>()({
                                  name: t.string(),
                                  comment: t.optional(t.string()),
                                })
                                
                                type Thing = t.ExtractType<typeof ThingValidator>

                              The type of Thing will be { name: string, comment?: string }. Note that the property types in the explicit type parameter (any) are ignored. The type parameter just indicates which properties are required and which are optional, and also allows you to mark properties readonly. These attributes will be reflected in t.ExtractType.

                              You can also use the t.optionalNullOr(t.string()) as a shorthand for t.optional(t.nullOr(t.string())).

                                t.record(t.string(), t.number())

                              A validator that requires the value to be Record<string, number>.

                                t.instanceOf(Date)

                              A validator that requires the value to be an instance of Date.

                                t.tuple(t.string(), t.number())

                              A validator that requires the value to be [string, number]. Accepts a variable number of arguments.

                                t.allOf(A, B)

                              A validator that requires the value to be A & B. Accepts a variable number of arguments, though type generation is only overloaded up to 8 arguments. For example:

                                const ThingType = t.simpleObject({ name: t.string() })
                                const CommentedType = t.simpleObject({ comment: t.string() })
                                
                                const CommentedThingType = t.allOf(ThingType, CommentedType)
                                
                                CommentedThingType.assert({ name: 'foo', comment: 'sweet' })

                                t.oneOf(t.string(), t.number())

                              A validator that requires the value to be string | number. Accepts a variable number of arguments, though type generation is only overloaded up to 8 arguments.

                                t.alias(name, type)

                              Creates a TypeAlias with the given name and type.

                              Type aliases serve two purposes:

                                * They allow you to create recursive type validators with t.ref()
                                * You can add custom constraints to them

                                t.ref(() => typeAlias)

                              Creates a reference to the given TypeAlias. See Recursive Types for examples.

                                t.Type<T>

                              The base class for all validator types.

                              T is the type of values it accepts.

                                accepts(input: any): boolean

                              Returns true if and only if input is the correct type.

                                assert<V extends T>(input: any, prefix = '', path?: (string | number | symbol)[]): V

                              Throws an error if input isn't the correct type.

                              prefix will be prepended to thrown error messages.

                              path will be prepended to validation error paths. If you are validating a function parameter named foo, pass ['foo'] for path to get clear error messages.

                                validate(input: any, prefix = '', path?: (string | number | symbol)[]): Validation<T>

                              Validates input, returning any errors in the Validation.

                              prefix and path are the same as in assert.

                                warn(input: any, prefix = '', path?: (string | number | symbol)[]): void

                              Logs a warning to the console if input isn't the correct type.

                                toString(): string

                              Returns a string representation of this type (using TS type syntax in most cases).

                                t.ExtractType<T extends Type<any>>

                              Gets the TypeScript type that a validator type accepts. For example:

                                import * as t from 'typescript-validators'
                                
                                const PostValidator = t.simpleObject({
                                  author: t.simpleObject({
                                    name: t.string(),
                                    username: t.string(),
                                  }),
                                  content: t.string(),
                                  tags: t.array(t.string()),
                                })
                                
                                type Post = t.ExtractType<typeof PostValidator>

                              Hover over Post in the IDE and you'll see, voilà:

                                type Post = {
                                  author: {
                                    name: string
                                    username: string
                                  }
                                  content: string
                                  tags: string[]
                                }

                                t.TypeAlias<T>

                                readonly name: string

                              The name of the alias.

                                addConstraint(...constraints: TypeConstraint<T>[]): this

                              Adds custom constraints. TypeConstraint<T> is a function (value: T) => string | null | undefined which returns nullish if value is valid, or otherwise a string describing why value is invalid.

                                Custom Constraints

                              It's nice to be able to validate that something is a number, but what if we want to make sure it's positive? We can do this by creating a type alias for number and adding a custom constraint to it:

                                const PositiveNumberType = t
                                  .alias('PositiveNumber', t.number())
                                  .addConstraint((value: number) => (value > 0 ? undefined : 'must be > 0'))
                                
                                PositiveNumberType.assert(-1)

                              The assertion will throw a t.RuntimeTypeError with the following message:

                                Value must be > 0
                                
                                Expected: PositiveNumber
                                
                                Actual Value: -1
                                
                                Actual Type: number
                                

                                Recursive Types

                              Creating validators for recursive types takes a bit of extra effort. Naively, we would want to do this:

                                const NodeType = t.object<{
                                  value: any
                                  left?: any
                                  right?: any
                                }>()({
                                  value: t.any(),
                                  left: t.optional(NodeType),
                                  right: t.optional(NodeType),
                                })

                              But t.optional(NodeType) causes the error Block-scoped variable 'NodeType' referenced before its declaration.

                              To work around this, we can create a TypeAlias and a reference to it:

                                const NodeType: t.TypeAlias<{
                                  value: any
                                  left?: Node
                                  right?: Node
                                }> = t.alias(
                                  'Node',
                                  t.object<{
                                    value: any
                                    left?: any
                                    right?: any
                                  }>()({
                                    value: t.any(),
                                    left: t.optional(t.ref(() => NodeType)),
                                    right: t.optional(t.ref(() => NodeType)),
                                  })
                                )
                                
                                type Node = t.ExtractType<typeof NodeType>
                                
                                NodeType.assert({
                                  value: 'foo',
                                  left: {
                                    value: 2,
                                    right: {
                                      value: 3,
                                    },
                                  },
                                  right: {
                                    value: 6,
                                  },
                                })

                              Notice how we use a thunk function in t.ref(() => NodeType) to avoid referencing NodeType before its declaration.

                          About

                          API input validators with user-friendly error output and TypeScript to ensure you don't miss any properties

                          Topics

                              api json typescript schema validation types json-schema validator validate assert type assertion js-schema defensive-programming validation-schema object-schema runtime-types

                          Resources

                            Readme

                          License

                            MIT license
                            Activity
                            Custom properties

                          Stars

                            12 stars

                          Watchers

                            3 watching

                          Forks

                            1 fork
                            Report repository

                        Releases 3

                            v1.0.2 Latest
                            Sep 12, 2020
                          + 2 releases

                        Packages 0

                          No packages published

                        Languages

                          * TypeScript 98.9%
                          * JavaScript 1.1%

    Footer

        © 2024 GitHub, Inc.

      Footer navigation

        * Terms
        * Privacy
        * Security
        * Status
        * Docs
        * Contact
        * Manage cookies
        * Do not share my personal information
      You can’t perform that action at this time.
GitHub - jcoreio/typescript-validators: API input validators with user-friendly error output and TypeScript to ensure you don't miss any properties
https://github.com/jcoreio/typescript-validators