mirror of
https://github.com/hanzoai/zod.git
synced 2026-09-24 17:04:49 +00:00
v4.0.0 (#4844)
* Update docs for zod@4 * Exclude tests * Update /mini entrypoint * Add locales, switch from /v4-mini to /mini * Update play * Update attw * Update resolution tests * Update release.yml * Add versioning.mdx * Update docs * 4.0.0 * Fix lint
This commit is contained in:
@@ -40,7 +40,6 @@ This is the Zod TypeScript-first schema validation library project. The project
|
||||
### Publishing
|
||||
- `pnpm prepublishOnly` - Run tests and build before publishing
|
||||
- `pnpm publish:jsr` - Publish to JSR (dry run)
|
||||
- `pnpm pub:beta` - Publish beta version
|
||||
|
||||
## Key Files
|
||||
|
||||
|
||||
@@ -40,10 +40,13 @@ jobs:
|
||||
uses: JS-DevTools/npm-publish@v3
|
||||
with:
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
dry-run: false
|
||||
# dry-run: true
|
||||
provenance: true
|
||||
package: ./packages/zod
|
||||
|
||||
- run: pnpm jsr publish --allow-slow-types # --dry-run
|
||||
working-directory: ./packages/zod
|
||||
|
||||
- name: Post-publish
|
||||
if: ${{ steps.publish.outputs.type }}
|
||||
run: |
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ if [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
||||
git status;
|
||||
exit 1
|
||||
fi
|
||||
pnpm semver-check
|
||||
pnpm check:semver
|
||||
lint-staged --verbose
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ if [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
||||
git status;
|
||||
exit 1
|
||||
fi
|
||||
pnpm semver-check
|
||||
pnpm check:semver
|
||||
pnpm test
|
||||
|
||||
+3
-3
@@ -19,6 +19,7 @@
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
"@types/benchmark": "^2.1.5",
|
||||
"@types/node": "^20.17.30",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@web-std/file": "^3.0.3",
|
||||
"arktype": "^2.1.19",
|
||||
"benchmark": "^2.1.4",
|
||||
@@ -46,7 +47,7 @@
|
||||
"vitest": "^2.1.9",
|
||||
"zod": "workspace:*",
|
||||
"zod3": "npm:zod@~3.24.0",
|
||||
"zshy": "^0.0.12"
|
||||
"zshy": "^0.0.13"
|
||||
},
|
||||
"lint-staged": {
|
||||
"packages/*/src/**/*.ts": [
|
||||
@@ -82,7 +83,6 @@
|
||||
"publish:jsr": "jsr publish --dry-run",
|
||||
"bundle:rollup": "rollup -c",
|
||||
"bundle:esbuild": "esbuild --bundle ./scratch/input.ts --outfile=./scratch/out_esbuild.js --bundle --format=esm",
|
||||
"pub:beta": "pnpm run -r pub:beta",
|
||||
"semver-check": "tsx scripts/semver-check.ts"
|
||||
"check:semver": "tsx scripts/check-semver.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { makeData } from "./benchUtil.js";
|
||||
import { metabench } from "./metabench.js";
|
||||
|
||||
import * as z4 from "zod/v4";
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
const a = z4.object({ a: z4.string() });
|
||||
const b = z.object({ a: z.string() });
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { makeData, randomPick, randomString } from "./benchUtil.js";
|
||||
import { metabench } from "./metabench.js";
|
||||
|
||||
import * as z4 from "zod/v4-mini";
|
||||
import * as z4 from "zod/mini";
|
||||
|
||||
const z4fields = {
|
||||
data1: z4.string(),
|
||||
|
||||
@@ -11,7 +11,7 @@ To validate data, you must first define a *schema*. Schemas represent *types*, f
|
||||
## Primitives
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
// primitive types
|
||||
z.string();
|
||||
@@ -136,7 +136,7 @@ z.string().startsWith("fourscore")
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.string().check(z.startsWith("fourscore"))
|
||||
```
|
||||
</Tab>
|
||||
@@ -151,7 +151,7 @@ z.string().startsWith("fourscore", {error: "Nice try, buddy"})
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.string().check(z.startsWith("fourscore", {error: "Nice try, buddy"}))
|
||||
```
|
||||
</Tab></Tabs> */}
|
||||
@@ -174,7 +174,7 @@ z.string().lowercase();
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.string().check(z.maxLength(5));
|
||||
z.string().check(z.minLength(5));
|
||||
z.string().check(z.length(5));
|
||||
@@ -199,7 +199,7 @@ z.string().toUpperCase(); // toUpperCase
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.string().check(z.trim()); // trim whitespace
|
||||
z.string().check(z.toLowerCase()); // toLowerCase
|
||||
z.string().check(z.toUpperCase()); // toUpperCase
|
||||
@@ -532,7 +532,7 @@ z.number().multipleOf(5); // alias .step(5)
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.number().check(z.gt(5));
|
||||
z.number().check(z.gte(5)); // alias .minimum(5)
|
||||
z.number().check(z.lt(5));
|
||||
@@ -587,7 +587,7 @@ z.bigint().multipleOf(5n); // alias `.step(5n)`
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.bigint().check(z.gt(5n));
|
||||
z.bigint().check(z.gte(5n)); // alias `.minimum(5n)`
|
||||
z.bigint().check(z.lt(5n));
|
||||
@@ -638,7 +638,7 @@ z.date().max(new Date(), { error: "Too young!" });
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.date().check(z.minimum(new Date("1900-01-01"), { error: "Too old!" }));
|
||||
z.date().check(z.maximum(new Date(), { error: "Too young!" }));
|
||||
```
|
||||
@@ -710,7 +710,7 @@ FishEnum.enum;
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]);
|
||||
|
||||
FishEnum.def.entries;
|
||||
@@ -731,7 +731,7 @@ const TunaOnly = FishEnum.exclude(["Salmon", "Trout"]);
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
// no equivalent
|
||||
|
||||
```
|
||||
@@ -750,7 +750,7 @@ const SalmonAndTroutOnly = FishEnum.extract(["Salmon", "Trout"]);
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
// no equivalent
|
||||
|
||||
```
|
||||
@@ -813,7 +813,7 @@ z.optional(z.literal("yoda")); // or z.literal("yoda").optional()
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.optional(z.literal("yoda"));
|
||||
```
|
||||
</Tab>
|
||||
@@ -828,7 +828,7 @@ optionalYoda.unwrap(); // ZodLiteral<"yoda">
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
optionalYoda.def.innerType; // ZodMiniLiteral<"yoda">
|
||||
```
|
||||
</Tab>
|
||||
@@ -845,7 +845,7 @@ z.nullable(z.literal("yoda")); // or z.literal("yoda").nullable()
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const nullableYoda = z.nullable(z.literal("yoda"));
|
||||
```
|
||||
</Tab>
|
||||
@@ -860,7 +860,7 @@ nullableYoda.unwrap(); // ZodLiteral<"yoda">
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
nullableYoda.def.innerType; // ZodMiniLiteral<"yoda">
|
||||
```
|
||||
</Tab>
|
||||
@@ -877,7 +877,7 @@ const nullishYoda = z.nullish(z.literal("yoda"));
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const nullishYoda = z.nullish(z.literal("yoda"));
|
||||
```
|
||||
</Tab>
|
||||
@@ -1024,7 +1024,7 @@ Dog.shape.age; // => number schema
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
Dog.def.shape.name; // => string schema
|
||||
Dog.def.shape.age; // => number schema
|
||||
```
|
||||
@@ -1043,7 +1043,7 @@ const keySchema = Dog.keyof();
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const keySchema = z.keyof(Dog);
|
||||
// => ZodEnum<["name", "age"]>
|
||||
```
|
||||
@@ -1063,7 +1063,7 @@ const DogWithBreed = Dog.extend({
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const DogWithBreed = z.extend(Dog, {
|
||||
breed: z.string(),
|
||||
});
|
||||
@@ -1115,7 +1115,7 @@ const JustTheTitle = Recipe.pick({ title: true });
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const JustTheTitle = z.pick(Recipe, { title: true });
|
||||
```
|
||||
</Tab>
|
||||
@@ -1133,7 +1133,7 @@ const RecipeNoId = Recipe.omit({ id: true });
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const RecipeNoId = z.omit(Recipe, { id: true });
|
||||
```
|
||||
</Tab>
|
||||
@@ -1155,7 +1155,7 @@ const PartialRecipe = Recipe.partial();
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const PartialRecipe = z.partial(Recipe);
|
||||
// { title?: string | undefined; description?: string | undefined; ingredients?: string[] | undefined }
|
||||
```
|
||||
@@ -1174,7 +1174,7 @@ const RecipeOptionalIngredients = Recipe.partial({
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const RecipeOptionalIngredients = z.partial(Recipe, {
|
||||
ingredients: true,
|
||||
});
|
||||
@@ -1197,7 +1197,7 @@ const RequiredRecipe = Recipe.required();
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const RequiredRecipe = z.required(Recipe);
|
||||
// { title: string; description: string; ingredients: string[] }
|
||||
```
|
||||
@@ -1214,7 +1214,7 @@ const RecipeRequiredDescription = Recipe.required({description: true});
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const RecipeRequiredDescription = z.required(Recipe, {description: true});
|
||||
// { title: string; description: string; ingredients: string[] }
|
||||
```
|
||||
@@ -1353,7 +1353,7 @@ const Activity = z.object({
|
||||
When in doubt, you can generally sidestep these issues with some carefully deployed type annotations on your getters. Due to the limitations described above, this is particularly necessary when using Zod Mini.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const Activity = z.object({
|
||||
name: z.string(),
|
||||
@@ -1377,7 +1377,7 @@ const stringArray = z.array(z.string()); // or z.string().array()
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const stringArray = z.array(z.string());
|
||||
```
|
||||
</Tab>
|
||||
@@ -1392,7 +1392,7 @@ stringArray.unwrap(); // => string schema
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
stringArray.def.element; // => string schema
|
||||
```
|
||||
</Tab>
|
||||
@@ -1409,7 +1409,7 @@ z.array(z.string()).length(5); // must contain 5 items exactly
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
z.array(z.string()).check(z.minLength(5)); // must contain 5 or more items
|
||||
z.array(z.string()).check(z.maxLength(5)); // must contain 5 or fewer items
|
||||
z.array(z.string()).check(z.length(5)); // must contain 5 items exactly
|
||||
@@ -1462,7 +1462,7 @@ stringOrNumber.options; // [ZodString, ZodNumber]
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
stringOrNumber.def.options; // [ZodString, ZodNumber]
|
||||
```
|
||||
</Tab>
|
||||
@@ -1690,7 +1690,7 @@ z.set(z.string()).max(5); // must contain 5 or fewer items
|
||||
z.set(z.string()).size(5); // must contain 5 items exactly
|
||||
```
|
||||
</Tab>
|
||||
<Tab value='zod/v4-mini'>
|
||||
<Tab value='Zod Mini'>
|
||||
```ts
|
||||
z.set(z.string()).check(z.minSize(5)); // must contain 5 or more items
|
||||
z.set(z.string()).check(z.maxSize(5)); // must contain 5 or fewer items
|
||||
@@ -1714,7 +1714,7 @@ fileSchema.mime(["image/png"]); // MIME type
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab value='zod/v4-mini'>
|
||||
<Tab value='Zod Mini'>
|
||||
```ts
|
||||
const fileSchema = z.file();
|
||||
|
||||
@@ -1796,7 +1796,7 @@ const myString = z.string().refine((val) => val.length <= 255);
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const myString = z.string().check(z.refine((val) => val.length <= 255));
|
||||
```
|
||||
</Tab>
|
||||
@@ -1819,7 +1819,7 @@ const myString = z.string().refine((val) => val.length > 8, {
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const myString = z.string().check(
|
||||
z.refine((val) => val.length > 8, { error: "Too short!" })
|
||||
);
|
||||
@@ -1848,7 +1848,7 @@ result.error.issues;
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const myString = z.string().check(
|
||||
z.refine((val) => val.length > 8, { error: "Too short!" }),
|
||||
z.refine((val) => val === val.toLowerCase(), { error: "Must be lowercase" })
|
||||
@@ -1881,7 +1881,7 @@ result.error!.issues;
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const myString = z.string().check(
|
||||
z.refine((val) => val.length > 8, { error: "Too short!", abort: true }),
|
||||
z.refine((val) => val === val.toLowerCase(), { error: "Must be lowercase", abort: true })
|
||||
@@ -2259,7 +2259,7 @@ castToString.parse(true); // => "true"
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const castToString = z.transform((val) => String(val));
|
||||
|
||||
z.parse(castToString, "asdf"); // => "asdf"
|
||||
@@ -2280,7 +2280,7 @@ type CastToString = z.infer<typeof castToString>; // string
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts zod/v4-mini
|
||||
```ts
|
||||
const castToString = z.transform((val) => String(val));
|
||||
|
||||
type CastToString = z.infer<typeof castToString>; // string
|
||||
|
||||
@@ -15,7 +15,7 @@ Before you can do anything else, you need to define a schema. For the purposes o
|
||||
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
@@ -25,7 +25,7 @@ const Player = z.object({
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
@@ -35,12 +35,12 @@ const Player = z.object({
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Accordions>
|
||||
{/* <Accordions>
|
||||
<Accordion title='Why the "/v4" suffix?'>
|
||||
To allow time for the ecosystem the migrate, there will be a transitionary period in which Zod 4 will be published alongside Zod 3 and consumable as a subpath import:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4"
|
||||
import * as z from "zod"
|
||||
```
|
||||
|
||||
During this transition window:
|
||||
@@ -51,7 +51,7 @@ const Player = z.object({
|
||||
|
||||
For a complete breakdown of the subpath versioning strategy, see the [associated writeup](https://github.com/colinhacks/zod/issues/4371).
|
||||
</Accordion>
|
||||
</Accordions>
|
||||
</Accordions> */}
|
||||
|
||||
## Parsing data
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
In Zod, validation errors are surfaced as instances of the `z.core.$ZodError` class.
|
||||
|
||||
> The `zod/v4` package uses a subclass of this called `z.ZodError` that implements some additional convenience methods.
|
||||
> The `ZodError` class in the `zod` package is a subclass that implements some additional convenience methods.
|
||||
|
||||
Instances of `$ZodError` contain an `.issues` array. Each issue contains a human-readable `message` and additional structured metadata about the issue.
|
||||
|
||||
@@ -16,7 +16,7 @@ Instances of `$ZodError` contain an `.issues` array. Each issue contains a human
|
||||
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const result = z.string().safeParse(12); // { success: false, error: ZodError }
|
||||
result.error.issues;
|
||||
@@ -32,7 +32,7 @@ result.error.issues;
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
const result = z.string().safeParse(12); // { success: false, error: z.core.$ZodError }
|
||||
result.error.issues;
|
||||
@@ -292,21 +292,21 @@ const result = schema.safeParse(12, {
|
||||
|
||||
To support internationalization of error message, Zod provides several built-in **locales**. These are exported from the `zod/v4/core` package.
|
||||
|
||||
> **Note** — The `zod/v4` library automatically loads the `en` locale automatically. The `zod/v4-mini` sub-package does not load any locale; instead all error messages default to `Invalid input`.
|
||||
> **Note** — The regular `zod` library automatically loads the `en` locale automatically. Zod Mini does not load any locale by default; instead all error messages default to `Invalid input`.
|
||||
|
||||
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import en from "zod/v4/locales/en.js"
|
||||
import * as z from "zod";
|
||||
import en from "zod/locales/en.js"
|
||||
|
||||
z.config(en());
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import en from "zod/v4/locales/en.js"
|
||||
import * as z from "zod/mini"
|
||||
import en from "zod/locales/en.js"
|
||||
|
||||
z.config(en());
|
||||
```
|
||||
@@ -316,7 +316,7 @@ z.config(en());
|
||||
To lazily load a locale, consider dynamic imports:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
async function loadLocale(locale: string) {
|
||||
const { default: locale } = await import(`zod/v4/locales/${locale}.js`);
|
||||
@@ -326,19 +326,19 @@ async function loadLocale(locale: string) {
|
||||
await loadLocale("fr");
|
||||
```
|
||||
|
||||
For convenience, all locales are exported as `z.locales` from `zod/v4`. In some bundlers, this may not be tree-shakable.
|
||||
For convenience, all locales are exported as `z.locales` from `"zod"`. In some bundlers, this may not be tree-shakable.
|
||||
|
||||
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
z.config(z.locales.en());
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
z.config(z.locales.en());
|
||||
```
|
||||
|
||||
@@ -10,7 +10,7 @@ Zod emphasizes _completeness_ and _correctness_ in its error reporting. In many
|
||||
Consider this simple object schema.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.strictObject({
|
||||
username: z.string(),
|
||||
@@ -170,4 +170,4 @@ The `formErrors` array contains any top-level errors (where `path` is `[]`). The
|
||||
```ts
|
||||
flattened.fieldErrors.username; // => [ 'Invalid input: expected string, received number' ]
|
||||
flattened.fieldErrors.favoriteNumbers; // => [ 'Invalid input: expected number, received string' ]
|
||||
```
|
||||
```
|
||||
|
||||
@@ -84,7 +84,7 @@ import { HeroLogo } from '../components/hero-logo';
|
||||
Zod is a TypeScript-first validation library. Using Zod, you can define *schemas* you can use to validate data, from a simple `string` to a complex nested object.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const User = z.object({
|
||||
name: z.string(),
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
To convert a Zod schema to JSON Schema, use the `z.toJSONSchema()` function.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
@@ -103,7 +103,7 @@ z.int32(); // => { type: "integer", exclusiveMinimum: ..., exclusiveMaximum: ...
|
||||
By default, `z.object()` schemas contain `additionalProperties: "false"`. This is an accurate representation of Zod's default behavior, as plain `z.object()` schema strip additional properties.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
@@ -122,7 +122,7 @@ z.toJSONSchema(schema)
|
||||
When converting to JSON Schema in `"input"` mode, `additionalProperties` is not set. See the [`io` docs](#io) for more information.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
@@ -261,7 +261,7 @@ In Zod, metadata is stored in registries. Zod exports a global registry `z.globa
|
||||
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
// `.meta()` is a convenience method for registering a schema in `z.globalRegistry`
|
||||
const emailSchema = z.string().meta({
|
||||
@@ -275,7 +275,7 @@ z.toJSONSchema(emailSchema);
|
||||
</Tab>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
// `.meta()` is a convenience method for registering a schema in `z.globalRegistry`
|
||||
const emailSchema = z.string().register(z.globalRegistry, {
|
||||
@@ -454,7 +454,7 @@ Passing a schema into `z.toJSONSchema()` will return a *self-contained* JSON Sch
|
||||
In other cases, you may have a set of Zod schemas you'd like to represent using multiple interlinked JSON Schemas, perhaps to write to `.json` files and serve from a web server.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const User = z.object({
|
||||
name: z.string(),
|
||||
|
||||
@@ -28,7 +28,7 @@ Any library built on top of Zod should include `"zod"` in `"peerDependencies"`.
|
||||
{
|
||||
// ...
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0"
|
||||
"zod": "^3.25.0 || ^4.0.0" // the "zod/v4" subpath was added in 3.25.0
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -39,29 +39,30 @@ During development, you need to meet your own peer dependency requirement, to do
|
||||
// package.json
|
||||
{
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0"
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zod": "^3.25.0"
|
||||
// generally, you should develop against the latest version of Zod
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How to support Zod 4?
|
||||
|
||||
To support Zod 4, update the minimum version for your `"zod"` peer dependency to `^3.25.0`.
|
||||
To support Zod 4, update the minimum version for your `"zod"` peer dependency to `^3.25.0 || ^4.0.0`.
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
// ...
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0"
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Starting with `v3.25.0`, the Zod 4 core package is available at a `/v4/core` subpath. Read the [Versioning in Zod 4](https://github.com/colinhacks/zod/issues/4371) writeup for full context on this versioning approach.
|
||||
Starting with `v3.25.0`, the Zod 4 core package is available at the `"zod/v4/core"` subpath. Read the [Versioning in Zod 4](https://github.com/colinhacks/zod/issues/4371) writeup for full context on this versioning approach.
|
||||
|
||||
```ts
|
||||
import * as z4 from "zod/v4/core";
|
||||
@@ -72,10 +73,11 @@ Import from these subpaths only. Think of them like "permalinks" to their respec
|
||||
- `"zod/v3"` for Zod 3 ✅
|
||||
- `"zod/v4/core"` for the Zod 4 Core package ✅
|
||||
|
||||
Do not import from these subpaths:
|
||||
You generally shouldn't be importing from any other paths. The Zod Core library is a shared library that undergirds both Zod 4 Classic and Zod 4 Mini. It's generally a bad idea to implement any functionality that is specific to one or the other. Do not import from these subpaths:
|
||||
|
||||
- `"zod"` — ❌ In 3.x releases, this exports Zod 3. In 4.x releases, this will export Zod 4. Use the permalinks instead.
|
||||
- `"zod/v4"` and `"zod/v4/mini"`— ❌ These subpaths are the homes of Zod 4 Classic and Mini, respectively. If you want your library to work with both Zod and Zod Mini, you should build against the base classes defined in `"zod/v4/core"`. If you reference classes from the `"zod/v4"` module, your library will not work with Zod Mini, and vice versa. This is extremely discouraged. Use `"zod/v4/core"` instead, which exports the `$`-prefixed subclasses that are extended by Zod Classic and Zod Mini. The internals of the classic & mini subclasses are identical; they only differ in which helper methods they implement.
|
||||
|
||||
- `"zod"` — ❌ In 3.x releases, this exports Zod 3. In a [future 4.x release](https://github.com/colinhacks/zod/issues/4371), this will export Zod 4. Use the permalinks instead.
|
||||
- `"zod/v4"`— ❌ This subpath is the home of Zod 4 "Classic". If you reference classes from the standard module, your library will not work with Zod Mini. This is extremely discouraged. Use `"zod/v4/core"` instead, which exports the `$`-prefixed subclasses that are extended by Zod Classic and Zod Mini. The internals of the classic & mini subclasses are identical; they only differ in which helper methods they implement.
|
||||
|
||||
## Do I need to publish a new major version?
|
||||
|
||||
@@ -115,7 +117,7 @@ if ("_zod" in schema) {
|
||||
|
||||
## How to support Zod and Zod Mini simultaneously?
|
||||
|
||||
Your library code should only import from `"zod/v4/core"`. This sub-package defines the interfaces, classes, and utilities that are shared between `zod/v4` and `zod/v4-mini`.
|
||||
Your library code should only import from `"zod/v4/core"`. This sub-package defines the interfaces, classes, and utilities that are shared between Zod and Zod Mini.
|
||||
|
||||
```ts
|
||||
// library code
|
||||
@@ -129,18 +131,18 @@ export function acceptObjectSchema<T extends z4.$ZodObject>(schema: T){
|
||||
}
|
||||
```
|
||||
|
||||
By building against the shared base interfaces, you can reliably support both sub-packages simultaneously. This function can accept both `zod/v4` and `zod/v4-mini` schemas.
|
||||
By building against the shared base interfaces, you can reliably support both sub-packages simultaneously. This function can accept both Zod and Zod Mini schemas.
|
||||
|
||||
```ts
|
||||
// user code
|
||||
import { acceptObjectSchema } from "your-library";
|
||||
|
||||
// Zod 4
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
acceptObjectSchema(z.object({ name: z.string() }));
|
||||
|
||||
// Zod 4 Mini
|
||||
import * as zm from "zod/v4-mini";
|
||||
import * as zm from "zod/mini";
|
||||
acceptObjectSchema(zm.object({ name: zm.string() }))
|
||||
```
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"---Zod 4---",
|
||||
"v4/index",
|
||||
"v4/changelog",
|
||||
"v4/versioning",
|
||||
"---Documentation---",
|
||||
"index",
|
||||
"basics",
|
||||
|
||||
@@ -14,7 +14,7 @@ It's often useful to associate a schema with some additional *metadata* for docu
|
||||
Metadata in Zod is handled via *registries*. Registries are collections of schemas, each associated with some *strongly-typed* metadata. To create a simple registry:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const myRegistry = z.registry<{ description: string }>();
|
||||
```
|
||||
@@ -98,7 +98,7 @@ export interface GlobalMeta {
|
||||
To register some metadata in `z.globalRegistry` for a schema:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const emailSchema = z.email().register(z.globalRegistry, {
|
||||
id: "email_address",
|
||||
@@ -185,7 +185,7 @@ You've already seen a simple example of a custom registry:
|
||||
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const myRegistry = z.registry<{ description: string };>();
|
||||
```
|
||||
@@ -197,7 +197,7 @@ Let's look at some more advanced patterns.
|
||||
It's often valuable for the metadata type to reference the *inferred type* of a schema. For instance, you may want an `examples` field to contain examples of the schema's output.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
type MyMeta = { examples: z.$output[] };
|
||||
const myRegistry = z.registry<MyMeta>();
|
||||
@@ -213,7 +213,7 @@ The special symbol `z.$output` is a reference to the schemas inferred output typ
|
||||
Pass a second generic to `z.registry()` to constrain the schema types that can be added to a registry. This registry only accepts string schemas.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const myRegistry = z.registry<{ description: string }, z.ZodString>();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ title: Zod Core
|
||||
import { Callout } from "fumadocs-ui/components/callout"
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
|
||||
This sub-package exports the core classes and utilities that are consumed by `zod/v4` and `zod/v4-mini`. It is not intended to be used directly; instead it's designed to be extended by other packages. It implements:
|
||||
This sub-package exports the core classes and utilities that are consumed by Zod and Zod Mini. It is not intended to be used directly; instead it's designed to be extended by other packages. It implements:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4/core";
|
||||
@@ -164,7 +164,7 @@ export type $ZodTypes =
|
||||
|
||||
## Internals
|
||||
|
||||
All `zod/v4/core` subclasses only contain a single property: `_zod`. This property is an object containing the schemas *internals*. The goal is to make `zod/v4/core` as extensible and unopinionated as possible. Other libraries can "build their own Zod" on top of these classes without `zod/v4/core` cluttering up the interface. Refer to the implementations of `zod/v4` and `zod/v4-mini` for examples of how to extend these classes.
|
||||
All `zod/v4/core` subclasses only contain a single property: `_zod`. This property is an object containing the schemas *internals*. The goal is to make `zod/v4/core` as extensible and unopinionated as possible. Other libraries can "build their own Zod" on top of these classes without `zod/v4/core` cluttering up the interface. Refer to the implementations of `zod` and `zod/mini` for examples of how to extend these classes.
|
||||
|
||||
The `_zod` internals property contains some notable properties:
|
||||
|
||||
@@ -379,8 +379,8 @@ The base class for all errors in Zod is `$ZodError`.
|
||||
|
||||
> For performance reasons, `$ZodError` *does not* extend the built-in `Error` class! So using `instanceof Error` will return `false`.
|
||||
|
||||
- The `zod/v4` package implements a subclass of `$ZodError` called `ZodError` with some additional convenience methods.
|
||||
- The `zod/v4-mini` sub-package directly uses `$ZodError`
|
||||
- The `zod` package implements a subclass of `$ZodError` called `ZodError` with some additional convenience methods.
|
||||
- The `zod/mini` sub-package directly uses `$ZodError`
|
||||
|
||||
```ts
|
||||
export class $ZodError<T = unknown> implements Error {
|
||||
|
||||
@@ -9,16 +9,16 @@ import { Callout } from 'fumadocs-ui/components/callout';
|
||||
**Note** — The docs for Zod Mini are interleaved with the regular Zod docs via tabbed code blocks. This page is designed to explain why Zod Mini exists, when to use it, and some key differences from regular Zod.
|
||||
</Callout>
|
||||
|
||||
The `zod/v4-mini` variant was introduced with the release of Zod 4. To try it:
|
||||
Zod Mini variant was introduced with the release of Zod 4. To try it:
|
||||
|
||||
```sh
|
||||
npm install zod@^3.25.0
|
||||
npm install zod@^4.0.0
|
||||
```
|
||||
|
||||
To import it:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
```
|
||||
|
||||
Zod Mini implements the exact same functionality as `zod`, but using a *functional*, *tree-shakable* API. If you're coming from `zod`, this means you generally will use *functions* in place of methods.
|
||||
@@ -35,7 +35,7 @@ const mySchema = z.nullable(z.optional(z.string()));
|
||||
|
||||
Tree-shaking is a technique used by modern bundlers to remove unused code from the final bundle. It's also referred to as *dead-code elimination*.
|
||||
|
||||
In regular Zod, schemas provide a range of convenience methods to perform some common operations (e.g. `.min()` on string schemas). Bundlers are generally not able to remove ("treeshake") unused method implementations from your bundle, but they are able to remove unused top-level functions. As such, the API of `zod/v4-mini` uses more functions than methods.
|
||||
In regular Zod, schemas provide a range of convenience methods to perform some common operations (e.g. `.min()` on string schemas). Bundlers are generally not able to remove ("treeshake") unused method implementations from your bundle, but they are able to remove unused top-level functions. As such, the API of Zod Mini uses more functions than methods.
|
||||
|
||||
```ts
|
||||
// regular Zod
|
||||
@@ -108,15 +108,15 @@ Generally, the round trip time to the server (`100-200ms`) will dwarf the time r
|
||||
|
||||
## `ZodMiniType`
|
||||
|
||||
All `zod/v4-mini` schemas extend the `z.ZodMiniType` base class, which in turn extends `z.core.$ZodType` from [`zod/v4/core`](/packages/core). While this class implements far fewer methods than `ZodType` in `zod`, some particularly useful methods remain.
|
||||
All Zod Mini schemas extend the `z.ZodMiniType` base class, which in turn extends `z.core.$ZodType` from [`zod/v4/core`](/packages/core). While this class implements far fewer methods than `ZodType` in `zod`, some particularly useful methods remain.
|
||||
|
||||
|
||||
### `.parse`
|
||||
|
||||
This is an obvious one. All `zod/v4-mini` schemas implement the same parsing methods as `zod`.
|
||||
This is an obvious one. All Zod Mini schemas implement the same parsing methods as `zod`.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const mySchema = z.string();
|
||||
|
||||
@@ -128,10 +128,10 @@ await mySchema.safeParseAsync('asdf')
|
||||
|
||||
### `.check()`
|
||||
|
||||
In `zod/v4` there are dedicated methods on schema subclasses for performing common checks:
|
||||
In regular Zod there are dedicated methods on schema subclasses for performing common checks:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
z.string()
|
||||
.min(5)
|
||||
@@ -140,10 +140,10 @@ z.string()
|
||||
.trim()
|
||||
```
|
||||
|
||||
In `zod/v4-mini` such methods aren't implemented. Instead you pass these checks into schemas using the `.check()` method:
|
||||
In Zod Mini such methods aren't implemented. Instead you pass these checks into schemas using the `.check()` method:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
z.string().check(
|
||||
z.minLength(5),
|
||||
@@ -207,7 +207,7 @@ z.string().register(myReg, { title: "My cool string schema" });
|
||||
For *branding* a schema. Refer to the [Branded types](/api#branded-types) docs for more information.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const USD = z.string().brand("USD");
|
||||
```
|
||||
@@ -225,12 +225,12 @@ mySchema.clone(mySchema._zod.def);
|
||||
|
||||
## No default locale
|
||||
|
||||
While `zod/v4` automatically loads the English (`en`) locale, `zod/v4-mini` does not. This reduces the bundle size in scenarios where error messages are unnecessary, localized to a non-English language, or otherwise customized.
|
||||
While regular Zod automatically loads the English (`en`) locale, Zod Mini does not. This reduces the bundle size in scenarios where error messages are unnecessary, localized to a non-English language, or otherwise customized.
|
||||
|
||||
This means, by default the `message` property of all issues will simply read `"Invalid input"`. To load the English locale:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
z.config(z.locales.en());
|
||||
```
|
||||
|
||||
@@ -185,7 +185,7 @@ pnpm add zod@canary # pnpm
|
||||
Creating a simple string schema
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
// creating a schema for strings
|
||||
const mySchema = z.string();
|
||||
@@ -202,7 +202,7 @@ mySchema.safeParse(12); // => { success: false; error: ZodError }
|
||||
Creating an object schema
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
const User = z.object({
|
||||
username: z.string(),
|
||||
@@ -220,7 +220,7 @@ type User = z.infer<typeof User>;
|
||||
## Primitives
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
// primitive values
|
||||
z.string();
|
||||
|
||||
@@ -9,7 +9,7 @@ The `zod/v4` package is the "flagship" library of the Zod ecosystem. It strikes
|
||||
Zod aims to provide a schema API that maps one-to-one to TypeScript's type system.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
@@ -30,7 +30,7 @@ z.string()
|
||||
All schemas extend the `z.ZodType` base class, which in turn extends `z.$ZodType` from [`zod/v4/core`](/packages/core). All instance of `ZodType` implement the following methods:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const mySchema = z.string();
|
||||
|
||||
|
||||
@@ -7,17 +7,17 @@ import { Tabs, Tab } from "fumadocs-ui/components/tabs";
|
||||
|
||||
> This migration guide aims to list the breaking changes in Zod 4 in order of highest to lowest impact. To learn more about the performance enhancements and new features of Zod 4, read the [introductory post](/v4).
|
||||
|
||||
To give the ecosystem time to migrate, Zod 4 will initially be published alongside Zod v3.25. To use Zod 4, upgrade to `[email protected]` or later:
|
||||
{/* To give the ecosystem time to migrate, Zod 4 will initially be published alongside Zod v3.25. To use Zod 4, upgrade to `[email protected]` or later: */}
|
||||
|
||||
```
|
||||
npm upgrade zod@^3.25.0
|
||||
npm upgrade zod@^4.0.0
|
||||
```
|
||||
|
||||
Zod 4 is available at the `"/v4"` subpath:
|
||||
{/* Zod 4 is available at the `"/v4"` subpath:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
```
|
||||
import * as z from "zod";
|
||||
``` */}
|
||||
|
||||
<Callout>
|
||||
**Note** — Zod 3 exported a number of undocumented quasi-internal utility types and functions that are not considered part of the public API. Changes to those are not documented here.
|
||||
@@ -172,7 +172,7 @@ Vitest uses special handling for `Error` subclasses that ignores enumerable prop
|
||||
The issue formats have been dramatically streamlined.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4"; // v4
|
||||
import * as z from "zod"; // v4
|
||||
|
||||
type IssueFormats =
|
||||
| z.core.$ZodIssueInvalidType
|
||||
@@ -191,7 +191,7 @@ type IssueFormats =
|
||||
Below is the list of Zod 3 issues types and their Zod 4 equivalent:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4"; // v3
|
||||
import * as z from "zod"; // v3
|
||||
|
||||
export type IssueFormats =
|
||||
| z.ZodInvalidTypeIssue // ♻️ renamed to z.core.$ZodIssueInvalidType
|
||||
@@ -694,7 +694,7 @@ The need for `z.ZodTypeAny` has been eliminated; just use `z.ZodType` instead.
|
||||
|
||||
### adds `z.core`
|
||||
|
||||
Many utility functions and types have been moved to the new `zod/v4/core` sub-package, to facilitate code sharing between `zod/v4` and `zod/v4-mini`.
|
||||
Many utility functions and types have been moved to the new `zod/v4/core` sub-package, to facilitate code sharing between Zod and Zod Mini.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4/core";
|
||||
@@ -704,10 +704,10 @@ function handleError(iss: z.$ZodError) {
|
||||
}
|
||||
```
|
||||
|
||||
For convenience, the contents of `zod/v4/core` are also re-exported from `zod/v4` and `zod/v4-mini` under the `z.core` namespace.
|
||||
For convenience, the contents of `zod/v4/core` are also re-exported from `zod` and `zod/mini` under the `z.core` namespace.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
function handleError(iss: z.core.$ZodError) {
|
||||
// do stuff
|
||||
@@ -727,10 +727,10 @@ This doesn't affect the user-facing APIs, but it's an internal change worth high
|
||||
|
||||
Previously both refinements and transformations lived inside a wrapper class called `ZodEffects`. That means adding either one to a schema would wrap the original schema in a `ZodEffects` instance. In Zod 4, refinements now live inside the schemas themselves. More accurately, each schema contains an array of "checks"; the concept of a "check" is new in Zod 4 and generalizes the concept of a refinement to include potentially side-effectful transforms like `z.toLowerCase()`.
|
||||
|
||||
This is particularly apparent in the `zod/v4-mini` API, which heavily relies on the `.check()` method to compose various validations together.
|
||||
This is particularly apparent in the Zod Mini API, which heavily relies on the `.check()` method to compose various validations together.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
z.string().check(
|
||||
z.minLength(10),
|
||||
@@ -745,7 +745,7 @@ z.string().check(
|
||||
Meanwhile, transforms have been moved into a dedicated `ZodTransform` class. This schema class represents an input transform; in fact, you can actually define standalone transformations now:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.transform(input => String(input));
|
||||
|
||||
|
||||
@@ -14,21 +14,20 @@ Huge thanks to [Clerk](https://go.clerk.com/zod-clerk), who supported my work on
|
||||
|
||||
## Versioning
|
||||
|
||||
To simplify the migration process both for users and Zod's ecosystem of associated libraries, Zod 4 will initially published alongside Zod 3 as part of the `[email protected]` release. Despite the version number, it is considered stable and ready for production use.
|
||||
{/* <Callout>
|
||||
**Update** — `[email protected]` has now been published to npm. To upgrad
|
||||
</Callout> */}
|
||||
|
||||
{/* To simplify the migration process both for users and Zod's ecosystem of associated libraries, Zod 4 will initially published alongside Zod 3 as part of the `[email protected]` release. Despite the version number, it is considered stable and ready for production use. */}
|
||||
|
||||
To upgrade:
|
||||
|
||||
```
|
||||
npm upgrade zod@^3.25.0
|
||||
npm upgrade zod@^4.0.0
|
||||
```
|
||||
|
||||
Then import Zod 4 from the `"/v4"` subpath:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
```
|
||||
|
||||
Down the road, when there's broad support for Zod 4, we'll publish `[email protected]` on npm. At this point, Zod 4 will be exported from the package root (`"zod"`). The `"zod/v4"` subpath will remain available. For a detailed writeup on the reasons for this versioning scheme, refer to [this issue](https://github.com/colinhacks/zod/issues/4371).
|
||||
{/* Down the road, when there's broad support for Zod 4, we'll publish `[email protected]` on npm. At this point, Zod 4 will be exported from the package root (`"zod"`). The `"zod/v4"` subpath will remain available. For a detailed writeup on the reasons for this versioning scheme, refer to [this issue](https://github.com/colinhacks/zod/issues/4371). */}
|
||||
|
||||
For a complete list of breaking changes, refer to the [Migration guide](/v4/changelog). This post focuses on new features & enhancements.
|
||||
|
||||
@@ -120,7 +119,7 @@ summary for z.object() safeParse
|
||||
Consider the following simple file:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
export const A = z.object({
|
||||
a: z.string(),
|
||||
@@ -152,7 +151,7 @@ $ pnpm bench object-with-extend
|
||||
More importantly, Zod 4 has redesigned and simplified the generics of `ZodObject` and other schema classes to avoid some pernicious "instantiation explosions". For instance, chaining `.extend()` and `.omit()` repeatedly—something that previously caused compiler issues:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
export const a = z.object({
|
||||
a: z.string(),
|
||||
@@ -266,7 +265,7 @@ In Zod 3, this took `4000ms` to compile; and adding additional calls to `.extend
|
||||
Consider the following simple script.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const schema = z.boolean();
|
||||
|
||||
@@ -277,25 +276,25 @@ It's about as simple as it gets when it comes to validation. That's intentional;
|
||||
|
||||
| Package | Bundle (gzip) |
|
||||
|---------|--------------|
|
||||
| `zod/v3` | `12.47kb` |
|
||||
| `zod/v4` | `5.36kb` |
|
||||
| Zod 3 | `12.47kb` |
|
||||
| Zod 4 | `5.36kb` |
|
||||
|
||||
The core bundle is ~57% smaller in Zod 4 (2.3x). That's good! But we can do a lot better.
|
||||
|
||||
## Introducing Zod Mini
|
||||
|
||||
Zod's method-heavy API is fundamentally difficult to tree-shake. Even our simple `z.boolean()` script pulls in the implementations of a bunch of methods we didn't use, like `.optional()`, `.array()`, etc. Writing slimmer implementations can only get you so far. That's where `zod/v4-mini` comes in.
|
||||
Zod's method-heavy API is fundamentally difficult to tree-shake. Even our simple `z.boolean()` script pulls in the implementations of a bunch of methods we didn't use, like `.optional()`, `.array()`, etc. Writing slimmer implementations can only get you so far. That's where Zod Mini comes in.
|
||||
|
||||
```sh
|
||||
npm install zod@^3.25.0
|
||||
```
|
||||
|
||||
It's a Zod variant with a functional, tree-shakable API that corresponds one-to-one with `zod`. Where Zod uses methods, `zod/v4-mini` generally uses wrapper functions:
|
||||
It's a Zod variant with a functional, tree-shakable API that corresponds one-to-one with `zod`. Where Zod uses methods, Zod Mini generally uses wrapper functions:
|
||||
|
||||
<Tabs groupId="lib" items={[ "Zod Mini", "Zod"]}>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
z.optional(z.string());
|
||||
|
||||
@@ -306,7 +305,7 @@ z.extend(z.object({ /* ... */ }), { age: z.number() });
|
||||
</Tab>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
z.string().optional();
|
||||
|
||||
@@ -317,10 +316,10 @@ z.object({ /* ... */ }).extend({ age: z.number() });
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Not all methods are gone! The parsing methods are identical in `zod/v4` and `zod/v4-mini`.
|
||||
Not all methods are gone! The parsing methods are identical in Zod and Zod Mini:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
z.string().parse("asdf");
|
||||
z.string().safeParse("asdf");
|
||||
@@ -333,7 +332,7 @@ There's also a general-purpose `.check()` method used to add refinements.
|
||||
<Tabs groupId="lib" items={[ "Zod Mini", "Zod"]}>
|
||||
<Tab value="Zod Mini">
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
z.array(z.number()).check(
|
||||
z.minLength(5),
|
||||
@@ -344,7 +343,7 @@ z.array(z.number()).check(
|
||||
</Tab>
|
||||
<Tab value="Zod">
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
z.array(z.number())
|
||||
.min(5)
|
||||
@@ -354,10 +353,10 @@ z.array(z.number())
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
The following top-level refinements are available in `zod/v4-mini`. It should be fairly self-explanatory which methods they correspond to.
|
||||
The following top-level refinements are available in Zod Mini. It should be fairly self-explanatory which Zod methods they correspond to.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
// custom checks
|
||||
z.refine();
|
||||
@@ -396,14 +395,14 @@ z.toUpperCase();
|
||||
```
|
||||
|
||||
|
||||
This more functional API makes it easier for bundlers to tree-shake the APIs you don't use. While `zod/v4` is still recommended for the majority of use cases, any projects with uncommonly strict bundle size constraints should consider `zod/v4-mini`.
|
||||
This more functional API makes it easier for bundlers to tree-shake the APIs you don't use. While regular Zod is still recommended for the majority of use cases, any projects with uncommonly strict bundle size constraints should consider Zod Mini.
|
||||
|
||||
### 6.6x reduction in core bundle size
|
||||
|
||||
Here's the script from above, updated to use `"zod/v4-mini"` instead of `"zod"`.
|
||||
Here's the script from above, updated to use `"zod/mini"` instead of `"zod"`.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
const schema = z.boolean();
|
||||
schema.parse(false);
|
||||
@@ -413,18 +412,18 @@ When we build this with `rollup`, the gzipped bundle size is `1.88kb`. That's an
|
||||
|
||||
| Package | Bundle (gzip) |
|
||||
|-----------|--------------|
|
||||
| `zod/v3` | `12.47kb` |
|
||||
| `zod/v4` | `5.36kb` |
|
||||
| `zod/v4-mini` | `1.88kb` |
|
||||
| Zod 3 | `12.47kb` |
|
||||
| Zod 4 (regular) | `5.36kb` |
|
||||
| Zod 4 (mini) | `1.88kb` |
|
||||
|
||||
Learn more on the dedicated [`zod/v4-mini`](/packages/mini) docs page. Complete API details are mixed into existing documentation pages; code blocks contain separate tabs for `"Zod"` and `"Zod Mini"` wherever their APIs diverge.
|
||||
Learn more on the dedicated [`zod/mini`](/packages/mini) docs page. Complete API details are mixed into existing documentation pages; code blocks contain separate tabs for `"Zod"` and `"Zod Mini"` wherever their APIs diverge.
|
||||
|
||||
## Metadata
|
||||
|
||||
Zod 4 introduces a new system for adding strongly-typed metadata to your schemas. Metadata isn't stored inside the schema itself; instead it's stored in a "schema registry" that associates a schema with some typed metadata. To create a registry with `z.registry()`:
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const myRegistry = z.registry<{ title: string; description: string }>();
|
||||
```
|
||||
@@ -494,7 +493,7 @@ z.string().meta({ description: "An email address" });
|
||||
Zod 4 introduces first-party JSON Schema conversion via `z.toJSONSchema()`.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const mySchema = z.object({name: z.string(), points: z.number()});
|
||||
|
||||
@@ -592,7 +591,7 @@ fileSchema.mime(["image/png"]); // MIME type
|
||||
Zod 4 introduces a new `locales` API for globally translating error messages into different languages.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
// configure English locale (default)
|
||||
z.config(z.locales.en());
|
||||
@@ -914,21 +913,21 @@ z.number().overwrite(val => val ** 2).max(100);
|
||||
|
||||
## An extensible foundation: `zod/v4/core`
|
||||
|
||||
While this will not be relevant to the majority of Zod users, it's worth highlighting. The addition of `zod/v4-mini` necessitated the creation of a shared sub-package `zod/v4/core` which contains the core functionality shared between `zod/v4` and `zod/v4-mini`.
|
||||
While this will not be relevant to the majority of Zod users, it's worth highlighting. The addition of Zod Mini necessitated the creation of a shared sub-package `zod/v4/core` which contains the core functionality shared between Zod and Zod Mini.
|
||||
|
||||
I was resistant to this at first, but now I see it as one of Zod 4's most important features. It lets Zod level up from a simple library to a fast validation "substrate" that can be sprinkled into other libraries.
|
||||
|
||||
If you're building a schema library, refer to the implementations of `zod/v4` and `zod/v4-mini` to see how to build on top of the foundation `zod/v4/core` provides. Don't hesitate to get in touch in GitHub discussions or via [X](https://x.com/colinhacks)/[Bluesky](https://bsky.app/profile/colinhacks.com) for help or feedback.
|
||||
If you're building a schema library, refer to the implementations of Zod and Zod Mini to see how to build on top of the foundation `zod/v4/core` provides. Don't hesitate to get in touch in GitHub discussions or via [X](https://x.com/colinhacks)/[Bluesky](https://bsky.app/profile/colinhacks.com) for help or feedback.
|
||||
|
||||
|
||||
## Wrapping up
|
||||
|
||||
I'm planning to write up a series of additional posts explaining the design process behind some major features like `zod/v4-mini`. I'll update this section as those get posted.
|
||||
I'm planning to write up a series of additional posts explaining the design process behind some major features like Zod Mini. I'll update this section as those get posted.
|
||||
|
||||
For library authors, there is now a dedicated [For library authors](/library-authors) guide that describes the best practices for building on top of Zod. It answers common questions about how to support Zod 3 & Zod 4 (including Mini) simultaneously.
|
||||
|
||||
```sh
|
||||
pnpm upgrade zod@^3.25.0
|
||||
pnpm upgrade zod@latest
|
||||
```
|
||||
|
||||
Happy parsing!<br/>
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
title: Versioning
|
||||
---
|
||||
|
||||
|
||||
import { Callout } from "fumadocs-ui/components/callout";
|
||||
|
||||
|
||||
### **Update — July 8th, 2025**
|
||||
|
||||
`[email protected]` has been published to `npm`. The package root (`"zod"`) now exports Zod 4. All other subpaths have not changed and will remain available forever.
|
||||
|
||||
To upgrade to Zod 4:
|
||||
|
||||
```
|
||||
npm upgrade zod@^4.0.0
|
||||
```
|
||||
|
||||
If you are using Zod 4, your existing imports (`"zod/v4"` and `"zod/v4-mini"`) will continue to work forever. However, after upgrading, you can *optionally* rewrite your imports as follows:
|
||||
|
||||
|
||||
| | Before | After |
|
||||
|----------------|-----------------|-------------|
|
||||
| Zod 4 | `"zod/v4"` | `"zod"` |
|
||||
| Zod 4 Mini | `"zod/v4-mini"` | `"zod/mini"`|
|
||||
| Zod 3 | `"zod"` | `"zod/v3"` |
|
||||
|
||||
|
||||
**Library authors** — if you've already implemented Zod 4 support according to the best practices outlined in the [Library authors](/library-authors) guide, bump your peer dependency to include `zod@^4.0.0`:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*There should be no other code changes necessary.* No code changes were made between the latest `3.25.x` release and `4.0.0`. This does not require a major version bump.
|
||||
|
||||
<details>
|
||||
<summary><strong>Some notes on subpath versioning</strong></summary>
|
||||
|
||||
Ultimately, the subpath versioning scheme was a necessary evil to force the ecosystem to upgrade in a non-breaking way. If I'd published `[email protected]` out of the gate, most libraries would have naively bumped their peer dependencies, forcing a "version bump avalanche" across the ecosystem.
|
||||
|
||||
As it stands, there is now [broad support](https://x.com/colinhacks/status/1932323805705482339) for Zod 4 across the ecosystem. No migration process is totally painless, but it seems like the "version avalanche" I'd feared didn't happen. By and large, libraries have been able to support Zod 3 and Zod 4 simultaneously: Hono, LangChain, React Hook Form, etc. Several ecosystem maintainers reached out to me specifically to indicate how convenient it was to incrementally add support for Zod 4 (something that would typically require a major version bump). Long story short: this approach worked great! Few other libraries are subject to the same constraints as Zod, but I strongly encourage other libraries with large associated ecosystems to consider a similar approach.
|
||||
</details>
|
||||
|
||||
## Versioning in Zod 4
|
||||
|
||||
This is a writeup of Zod 4's approach to versioning, with the goal of making it easier for users and Zod's ecosystem of associated libraries to migrate to Zod 4.
|
||||
|
||||
The general approach:
|
||||
|
||||
- Zod 4 will not initially be published as `[email protected]` on npm. Instead it will be exported at a subpath (`"zod/v4"`) alongside `[email protected]`
|
||||
- Despite this, Zod 4 is considered stable and production-ready
|
||||
- Zod 3 will continue to be exported from the package root (`"zod"`) as well as a new subpath `"zod/v3"`. It will continue to receive bug fixes & stability improvements.
|
||||
|
||||
> This approach is analogous to how Golang handles major version changes: https://go.dev/doc/modules/major-version
|
||||
|
||||
Sometime later:
|
||||
|
||||
- The package root (`"zod"`) will switch over from exporting Zod 3 to Zod 4
|
||||
- At this point `[email protected]` will get published to npm
|
||||
- The `"zod/v4"` subpath will remain available forever
|
||||
|
||||
## Why?
|
||||
|
||||
Zod occupies a unique place in the ecosystem. Many libraries/frameworks in the ecosystem accept user-defined Zod schemas. This means their user-facing API is strongly coupled to Zod and its various classes/interfaces/utilities. For these libraries/frameworks, a breaking change to Zod necessarily causes a breaking change for their users. A Zod 3 `ZodType` is not assignable to a Zod 4 `ZodType`.
|
||||
|
||||
|
||||
### Why can't libraries just support v3 and v4 simultaneously?
|
||||
|
||||
Unfortunately the limitations of peerDependencies (and inconsistencies between package managers) make it extremely difficult to elegantly support two major versions of one library simultaneously.
|
||||
|
||||
If I naively published `[email protected]` to npm, the vast majority of the libraries in Zod's ecosystem would need to publish a new major version to properly support Zod 4, include some high-profile libraries like the AI SDK. It would trigger a "version bump avalanche" across the ecosystem and generally create a huge amount of frustration and work.
|
||||
|
||||
With subpath versioning, we solve this problem. it provides a straightforward way for libraries to support Zod 3 and Zod 4 (including Zod Mini) simultaneously. They can continue defining a single peerDependency on `"zod"`; no need for more arcane solutions like npm aliases, optional peer dependencies, a `"zod-compat"` package, or other such hacks.
|
||||
|
||||
Libraries will need to bump the minimum version of their `"zod"` peer dependency to `zod@^3.25.0`. They can then reference both Zod 3 and Zod 4 in their implementation:
|
||||
|
||||
```ts
|
||||
import * as z3 from "zod/v3"
|
||||
import * as z4 from "zod/v4"
|
||||
```
|
||||
|
||||
Later, once there's broad support for v4, we'll bump the major version on `npm` and start exporting Zod 4 from the package root, completing the transition. (This has now happened—see the note at the top of this page.)
|
||||
|
||||
As long as libraries are importing exclusively from the associated subpaths (not the root), their implementations will continue to work across the major version bump without code changes.
|
||||
|
||||
While it may seem unorthodox (at least for people who don't use Go!), this is the only approach I'm aware of that enables a clean, incremental migration path for both Zod's users and the libraries in the broader ecosystem.
|
||||
|
||||
---
|
||||
|
||||
A deeper dive into why peer dependencies don't work in this situation.
|
||||
|
||||
Imagine you're a library trying to build a function `acceptSchema` that accepts a Zod schema. You want to be able to accept Zod 3 or Zod 4 schemas. In this hypothetical, I'm imagine Zod 4 was published as `zod@4` on npm, no subpaths. Here are your options:
|
||||
|
||||
1. Install both zod@3 and zod@4 as `dependencies` simultaneously using npm aliases. This works but you end up including your own copies of both Zod 3 and Zod 4. You have no guarantee that your user's Zod schemas are instances of the same z.ZodType class you're pulling from dependencies (`instanceof` checks will probably fail).
|
||||
|
||||
2. Use a peer dependency that spans multiple major versions: `"zod@>=3.0.0"` …but when developing a library you’d still need to pick a version to develop against. Usually you'd install this as a dev dependency. The onus is on you to painstakingly ensure your code works, character-for-character, across both versions. This is impossible in the case of Zod 3 & Zod 4 because a number of very fundamental classes have simplified/different generics.
|
||||
|
||||
3. Optional peer dependencies. i just couldn't find a straight answer about how to reliably determine which peer dep is installed at runtime across all platforms. Many answers online will say "use dynamic imports in a try/catch to check it a package exists". Those folks are assuming you're on the backend because no frontend bundlers have no affordance for this. They'll fail when you try to bundle a dependency that isn't installed. Obviuosly it doesn't matter if you're inside a try/catch during a build step. Also: since we're talking about multiple versions of the same library, you'd need to use npm aliases to differentiate the two versions in your `package.json`. Versions of npm as recent as v10 cannot handle the combination of peer dependencies + npm aliases.
|
||||
|
||||
4. `zod-compat`. This extremely hand-wavy solution you see online is "define interfaces for each version that represents some basic functionality". Basically some utility types libraries can use to approximate the real deal. This is error prone, a ton of work, needs to be kept synchronized with the real implementations, and ultimately libraries are developing against a shadow version of your library that probably lacks detail. It also only works for types: if a library depends on any runtime code in Zod it falls apart.
|
||||
|
||||
Hence, subpaths.
|
||||
@@ -47,6 +47,24 @@ describe("Are The Types Wrong (attw) tests", () => {
|
||||
|
||||
***********************************
|
||||
|
||||
"zod/mini"
|
||||
|
||||
node10: 🟢
|
||||
node16 (from CJS): 🟢 (CJS)
|
||||
node16 (from ESM): 🎭 Masquerading as CJS
|
||||
bundler: 🟢
|
||||
|
||||
***********************************
|
||||
|
||||
"zod/locales"
|
||||
|
||||
node10: 🟢
|
||||
node16 (from CJS): 🟢 (CJS)
|
||||
node16 (from ESM): 🎭 Masquerading as CJS
|
||||
bundler: 🟢
|
||||
|
||||
***********************************
|
||||
|
||||
"zod/v3"
|
||||
|
||||
node10: 🟢
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as z1 from "zod";
|
||||
import z2 from "zod";
|
||||
import { z as z3 } from "zod";
|
||||
import * as z7 from "zod/mini";
|
||||
import * as z5 from "zod/v3";
|
||||
import * as z4 from "zod/v4";
|
||||
import * as z7 from "zod/v4-mini";
|
||||
import * as z8 from "zod/v4-mini";
|
||||
import fr from "zod/v4/locales/fr.cjs";
|
||||
import * as z6 from "zod/v4/mini";
|
||||
|
||||
@@ -14,6 +15,7 @@ console.log(z4.string().parse("Hello, world!"));
|
||||
console.log(z5.string().parse("Hello, world!"));
|
||||
console.log(z6.string().parse("Hello, world!"));
|
||||
console.log(z7.string().parse("Hello, world!"));
|
||||
console.log(z8.string().parse("Hello, world!"));
|
||||
|
||||
z4.config(fr());
|
||||
const schema = z4.object({
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as z1 from "zod";
|
||||
import z2 from "zod";
|
||||
import { z as z3 } from "zod";
|
||||
import * as z7 from "zod/mini";
|
||||
import * as z5 from "zod/v3";
|
||||
import * as z4 from "zod/v4";
|
||||
import * as z7 from "zod/v4-mini";
|
||||
import * as z8 from "zod/v4-mini";
|
||||
import fr from "zod/v4/locales/fr.js";
|
||||
import * as z6 from "zod/v4/mini";
|
||||
|
||||
@@ -14,6 +15,7 @@ console.log(z4.string().parse("Hello, world!"));
|
||||
console.log(z5.string().parse("Hello, world!"));
|
||||
console.log(z6.string().parse("Hello, world!"));
|
||||
console.log(z7.string().parse("Hello, world!"));
|
||||
console.log(z8.string().parse("Hello, world!"));
|
||||
|
||||
z4.config(fr());
|
||||
const schema = z4.object({
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as z1 from "zod";
|
||||
import z2 from "zod";
|
||||
import { z as z3 } from "zod";
|
||||
import * as z7 from "zod/mini";
|
||||
import * as z5 from "zod/v3";
|
||||
import * as z4 from "zod/v4";
|
||||
import * as z7 from "zod/v4-mini";
|
||||
import * as z8 from "zod/v4-mini";
|
||||
import fr from "zod/v4/locales/fr.js";
|
||||
import * as z6 from "zod/v4/mini";
|
||||
|
||||
@@ -14,6 +15,7 @@ console.log(z4.string().parse("Hello, world!"));
|
||||
console.log(z5.string().parse("Hello, world!"));
|
||||
console.log(z6.string().parse("Hello, world!"));
|
||||
console.log(z7.string().parse("Hello, world!"));
|
||||
console.log(z8.string().parse("Hello, world!"));
|
||||
|
||||
z4.config(fr());
|
||||
const schema = z4.object({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
z.string().check(
|
||||
z.minLength(5),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
z.config(z.locales.en());
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const schema = z.boolean();
|
||||
console.log(schema.parse(true));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
export const schema = z.object({
|
||||
name: z.string(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const schema = z.object({ a: z.string(), b: z.number(), c: z.boolean() });
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod/v4-mini"
|
||||
import * as z from "zod/mini"
|
||||
|
||||
const schema = z.string().check(z.minLength(5));
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const User = z.object({
|
||||
name: z.string(),
|
||||
@@ -104,7 +104,7 @@ npm install zod
|
||||
Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.
|
||||
|
||||
```ts
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
|
||||
+10
-3
@@ -1,12 +1,19 @@
|
||||
{
|
||||
"name": "@zod/zod",
|
||||
"version": "4.0.0-alpha.0",
|
||||
"version": "4.0.0",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts",
|
||||
"./package.json": "./package.json"
|
||||
"./mini": "./src/v4/mini/index.ts",
|
||||
"./v3": "./src/v3/index.ts",
|
||||
"./v4": "./src/v4/index.ts",
|
||||
"./v4-mini": "./src/v4-mini/index.ts",
|
||||
"./v4/mini": "./src/v4/mini/index.ts",
|
||||
"./v4/core": "./src/v4/core/index.ts",
|
||||
"./v4/locales": "./src/v4/locales/index.ts"
|
||||
},
|
||||
"publish": {
|
||||
"include": ["src", "LICENSE", "package.json", "README.md"],
|
||||
"exclude": ["tests", "dist"]
|
||||
"exclude": ["**/tests/**", "dist"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zod",
|
||||
"version": "3.25.76",
|
||||
"version": "4.0.0",
|
||||
"type": "module",
|
||||
"author": "Colin McDonnell <[email protected]>",
|
||||
"description": "TypeScript-first schema declaration and validation library with static type inference",
|
||||
@@ -31,6 +31,8 @@
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts",
|
||||
"./mini": "./src/mini/index.ts",
|
||||
"./locales": "./src/locales/index.ts",
|
||||
"./v3": "./src/v3/index.ts",
|
||||
"./v4": "./src/v4/index.ts",
|
||||
"./v4-mini": "./src/v4-mini/index.ts",
|
||||
@@ -51,6 +53,18 @@
|
||||
"import": "./index.js",
|
||||
"require": "./index.cjs"
|
||||
},
|
||||
"./mini": {
|
||||
"@zod/source": "./src/mini/index.ts",
|
||||
"types": "./mini/index.d.cts",
|
||||
"import": "./mini/index.js",
|
||||
"require": "./mini/index.cjs"
|
||||
},
|
||||
"./locales": {
|
||||
"@zod/source": "./src/locales/index.ts",
|
||||
"types": "./locales/index.d.cts",
|
||||
"import": "./locales/index.js",
|
||||
"require": "./locales/index.cjs"
|
||||
},
|
||||
"./v3": {
|
||||
"@zod/source": "./src/v3/index.ts",
|
||||
"types": "./v3/index.d.cts",
|
||||
@@ -112,7 +126,6 @@
|
||||
"postbuild": "pnpm biome check --write .",
|
||||
"test:watch": "pnpm vitest",
|
||||
"test": "pnpm vitest run",
|
||||
"bump:beta": "pnpm version \"v$(pnpm pkg get version | jq -r)-beta.$(date +%Y%m%dT%H%M%S)\"",
|
||||
"pub:beta": "pnpm bump:beta && pnpm publish --tag next --publish-branch v4 --no-git-checks --dry-run"
|
||||
"prepublishOnly": "tsx ../../scripts/check-versions.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "./v3/external.js";
|
||||
export * from "./v3/external.js";
|
||||
import * as z from "./v4/classic/external.js";
|
||||
export * from "./v4/classic/external.js";
|
||||
export { z };
|
||||
export default z;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from "../v4/locales/index.js";
|
||||
@@ -0,0 +1 @@
|
||||
export * from "../v4/mini/index.js";
|
||||
@@ -33,12 +33,12 @@ export class Doc {
|
||||
}
|
||||
}
|
||||
|
||||
compile() {
|
||||
compile(): any {
|
||||
const F = Function;
|
||||
const args = this?.args;
|
||||
const content = this?.content ?? [``];
|
||||
const lines = [...content.map((x) => ` ${x}`)];
|
||||
// console.log(lines.join("\n"));
|
||||
return new F(...args, lines.join("\n"));
|
||||
return new F(...args, lines.join("\n")) as any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export const browserEmail: RegExp =
|
||||
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression
|
||||
|
||||
export const _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
const _emoji: string = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
export function emoji(): RegExp {
|
||||
return new RegExp(_emoji, "u");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
test("assignability", () => {
|
||||
// $ZodString
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
import { util as zc } from "zod/v4/core";
|
||||
|
||||
test("min/max", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
test("no locale by default", () => {
|
||||
const result = z.safeParse(z.string(), 12);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
test("z.boolean", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
test("z.number", () => {
|
||||
const a = z.number();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
test("z.object", () => {
|
||||
const a = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
declare module "zod/v4/core" {
|
||||
interface $ZodType {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4-mini";
|
||||
import { z } from "zod/mini";
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const data = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4-mini";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
const FAIL = { success: false };
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
"module": "nodenext",
|
||||
"customConditions": ["@zod/source"],
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
"include": ["**/*.ts", "../../scripts/check-versions.ts"]
|
||||
}
|
||||
|
||||
@@ -1,19 +1,3 @@
|
||||
import * as z from "zod/v4";
|
||||
import * as z from "zod";
|
||||
|
||||
// ID is branded. Brand under the hood is an obj structur {...}
|
||||
const Id = z.string().brand("Id");
|
||||
const Obj = z.object({
|
||||
id: Id,
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const result = Obj.safeParse({});
|
||||
if (result.error) {
|
||||
const tree = z.treeifyError(result.error);
|
||||
// Compare the two types
|
||||
// name is looked up as primitive string
|
||||
// id is looked up as object with its properties, ending up with the properties of string
|
||||
// this is because of the brand obj intersection with string
|
||||
type TreeId = NonNullable<(typeof tree)["properties"]>["id"];
|
||||
type TreeName = NonNullable<(typeof tree)["properties"]>["name"];
|
||||
}
|
||||
z;
|
||||
|
||||
Generated
+22
-14
@@ -20,6 +20,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^20.17.30
|
||||
version: 20.17.30
|
||||
'@types/semver':
|
||||
specifier: ^7.7.0
|
||||
version: 7.7.0
|
||||
'@web-std/file':
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3
|
||||
@@ -102,8 +105,8 @@ importers:
|
||||
specifier: npm:zod@~3.24.0
|
||||
version: [email protected]
|
||||
zshy:
|
||||
specifier: ^0.0.12
|
||||
version: 0.0.12([email protected])
|
||||
specifier: ^0.0.13
|
||||
version: 0.0.13([email protected])
|
||||
|
||||
packages/bench:
|
||||
devDependencies:
|
||||
@@ -127,7 +130,7 @@ importers:
|
||||
dependencies:
|
||||
'@inkeep/cxkit-react':
|
||||
specifier: ^0.5.80
|
||||
version: 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)
|
||||
version: 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)
|
||||
'@radix-ui/react-accordion':
|
||||
specifier: ^1.2.4
|
||||
version: 1.2.4(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
|
||||
@@ -2657,6 +2660,9 @@ packages:
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
||||
|
||||
@@ -5755,8 +5761,8 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-5pp8Q0PNDaNcUptGiBE9akyioJh3RJpagIxrLtAVMR9IxwcSZiOsJD/1/98CyhItdTlI2H91MfhhLzRlU+fifA==}
|
||||
|
||||
[email protected]2:
|
||||
resolution: {integrity: sha512-5txlxh4PoZIU4zRdXbhreeY/bnEgUvmeOXXM6TKH4FdqKDTlyk2H99SF9RmB+/U4ciAGXeXkD79Z/bQrN++pCQ==}
|
||||
[email protected]3:
|
||||
resolution: {integrity: sha512-OyEo2NoCbCtpY9Pr5PO/7Nna6RjDQnp8k3t2df1UKRe4rMH4A0D4KqDteDBosdQ4pYiTNW927CXZrflcEFNXpQ==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '>5.5.0'
|
||||
@@ -6232,7 +6238,7 @@ snapshots:
|
||||
|
||||
'@inkeep/[email protected]': {}
|
||||
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)':
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)':
|
||||
dependencies:
|
||||
'@inkeep/cxkit-color-mode': 0.5.80
|
||||
'@inkeep/cxkit-theme': 0.5.80
|
||||
@@ -6266,7 +6272,7 @@ snapshots:
|
||||
lucide-react: 0.503.0([email protected])
|
||||
marked: 15.0.12
|
||||
merge-anything: 5.1.7
|
||||
openai: 4.78.1([email protected])(zod@packages+zod)
|
||||
openai: 4.78.1([email protected])(zod@3.25.68)
|
||||
prism-react-renderer: 2.4.1([email protected])
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0([email protected])
|
||||
@@ -6287,9 +6293,9 @@ snapshots:
|
||||
- supports-color
|
||||
- zod
|
||||
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)':
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)':
|
||||
dependencies:
|
||||
'@inkeep/cxkit-styled': 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)
|
||||
'@inkeep/cxkit-styled': 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)
|
||||
'@radix-ui/react-use-controllable-state': 1.1.0(@types/[email protected])([email protected])
|
||||
lucide-react: 0.503.0([email protected])
|
||||
transitivePeerDependencies:
|
||||
@@ -6301,9 +6307,9 @@ snapshots:
|
||||
- supports-color
|
||||
- zod
|
||||
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)':
|
||||
'@inkeep/[email protected](@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)':
|
||||
dependencies:
|
||||
'@inkeep/cxkit-primitives': 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@packages+zod)
|
||||
'@inkeep/cxkit-primitives': 0.5.80(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])(zod@3.25.68)
|
||||
class-variance-authority: 0.7.1
|
||||
clsx: 2.1.1
|
||||
merge-anything: 5.1.7
|
||||
@@ -7821,6 +7827,8 @@ snapshots:
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
@@ -10153,7 +10161,7 @@ snapshots:
|
||||
regex: 6.0.1
|
||||
regex-recursion: 6.0.2
|
||||
|
||||
[email protected]([email protected])(zod@packages+zod):
|
||||
[email protected]([email protected])(zod@3.25.68):
|
||||
dependencies:
|
||||
'@types/node': 18.19.103
|
||||
'@types/node-fetch': 2.6.12
|
||||
@@ -10163,7 +10171,7 @@ snapshots:
|
||||
formdata-node: 4.4.1
|
||||
node-fetch: 2.7.0([email protected])
|
||||
optionalDependencies:
|
||||
zod: link:packages/zod
|
||||
zod: 3.25.68
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -11542,7 +11550,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@zod/core': 0.8.1
|
||||
|
||||
[email protected]2([email protected]):
|
||||
[email protected]3([email protected]):
|
||||
dependencies:
|
||||
arg: 5.0.2
|
||||
globby: 14.1.0
|
||||
|
||||
@@ -25,7 +25,7 @@ try {
|
||||
}
|
||||
|
||||
console.log(`Valid semver version: ${version}`);
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { version } from "../packages/zod/src/v4/core/versions.js";
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
// Get zod package path
|
||||
const zodPackagePath = join(__dirname, "..", "packages", "zod");
|
||||
|
||||
// Read package.json version
|
||||
const packageJsonPath = join(zodPackagePath, "package.json");
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
||||
const packageJsonVersion = packageJson.version as string;
|
||||
if (typeof packageJsonVersion !== "string") {
|
||||
throw new Error("package.json version is not a string");
|
||||
}
|
||||
|
||||
// Read jsr.json version
|
||||
const jsrJsonPath = join(zodPackagePath, "jsr.json");
|
||||
const jsrJson = JSON.parse(readFileSync(jsrJsonPath, "utf8"));
|
||||
const jsrJsonVersion = jsrJson.version as string;
|
||||
if (typeof jsrJsonVersion !== "string") {
|
||||
throw new Error("jsr.json version is not a string");
|
||||
}
|
||||
|
||||
// read tag
|
||||
const tag = process.env.npm_config_tag || "latest";
|
||||
if (tag === "latest") {
|
||||
// e.g. "beta"
|
||||
const xyz = /^\d+\.\d+\.\d+$/;
|
||||
if (!xyz.test(packageJsonVersion)) {
|
||||
throw new Error("package.json version is not in x.y.z format");
|
||||
}
|
||||
if (!xyz.test(jsrJsonVersion)) {
|
||||
throw new Error("jsr.json version is not in x.y.z format");
|
||||
}
|
||||
}
|
||||
|
||||
// Get version from versions.ts
|
||||
const versionsVersion = `${version.major}.${version.minor}.${version.patch}`;
|
||||
|
||||
// Compare versions
|
||||
const isValid =
|
||||
tag === "latest" ? packageJsonVersion === versionsVersion : packageJsonVersion.startsWith(versionsVersion);
|
||||
if (!isValid) {
|
||||
console.error(`❌ Version mismatch:`);
|
||||
console.error(` package.json: ${packageJsonVersion}`);
|
||||
console.error(` versions.ts: ${versionsVersion}`);
|
||||
console.error(` tag: ${tag}`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
if (tag === "latest") {
|
||||
console.log(`✅ Versions match: ${packageJsonVersion} === ${versionsVersion}`);
|
||||
} else {
|
||||
console.log(`✅ Versions match: ${packageJsonVersion} starts with ${versionsVersion}`);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
"extends": "./.configs/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"customConditions": ["@zod/source"],
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16"
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext"
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.mts", "**/*.cts"],
|
||||
"exclude": ["**/*.d.ts", "**/*.d.cts", "**/*.d.mts", "packages/docs"]
|
||||
|
||||
Reference in New Issue
Block a user