diff --git a/README.md b/README.md index dcf61e2fa..8389fda2b 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,8 @@ * [valita](https://github.com/badrap/valita) * [Vality](https://github.com/jeengbe/vality) * [yup](https://github.com/jquense/yup) -* [zod](https://github.com/vriad/zod) +* [zod](https://github.com/colinhacks/zod) +* [zod (v4)](https://github.com/colinhacks/zod/tree/v4) ## Criteria diff --git a/cases/index.ts b/cases/index.ts index c9e547624..a4a9ccc27 100644 --- a/cases/index.ts +++ b/cases/index.ts @@ -54,6 +54,7 @@ export const cases = [ 'vality', 'yup', 'zod', + 'zod4', 'deepkit', 'effect-schema', 'ts-auto-guard', diff --git a/cases/zod4.ts b/cases/zod4.ts new file mode 100644 index 000000000..15b2072d8 --- /dev/null +++ b/cases/zod4.ts @@ -0,0 +1,90 @@ +import * as z from 'zod4'; +import { createCase } from '../benchmarks'; + +createCase('zod4', 'parseSafe', () => { + const dataType = z.interface({ + number: z.number(), + negNumber: z.number(), + maxNumber: z.number(), + string: z.string(), + longString: z.string(), + boolean: z.boolean(), + deeplyNested: z.interface({ + foo: z.string(), + num: z.number(), + bool: z.boolean(), + }), + }); + + return data => { + return dataType.parse(data); + }; +}); + +createCase('zod4', 'parseStrict', () => { + const dataType = z + .interface({ + number: z.number(), + negNumber: z.number(), + maxNumber: z.number(), + string: z.string(), + longString: z.string(), + boolean: z.boolean(), + deeplyNested: z + .interface({ + foo: z.string(), + num: z.number(), + bool: z.boolean(), + }) + .strict(), + }) + .strict(); + + return data => { + return dataType.parse(data); + }; +}); + +createCase('zod4', 'assertLoose', () => { + const dataType = z.looseInterface({ + number: z.number(), + negNumber: z.number(), + maxNumber: z.number(), + string: z.string(), + longString: z.string(), + boolean: z.boolean(), + deeplyNested: z.looseInterface({ + foo: z.string(), + num: z.number(), + bool: z.boolean(), + }), + }); + + return data => { + dataType.parse(data); + + return true; + }; +}); + +createCase('zod4', 'assertStrict', () => { + const dataType = z.strictInterface({ + number: z.number(), + negNumber: z.number(), + maxNumber: z.number(), + string: z.string(), + longString: z.string(), + boolean: z.boolean(), + deeplyNested: z.strictInterface({ + foo: z.string(), + num: z.number(), + bool: z.boolean(), + }), + }); + + return data => { + dataType.parse(data); + + return true; + }; +}); diff --git a/package-lock.json b/package-lock.json index 627fba27a..765df6a5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,7 +84,8 @@ "vega": "5.33.0", "vega-lite": "5.11.0", "yup": "1.6.1", - "zod": "3.24.2" + "zod": "3.24.2", + "zod4": "npm:zod@next" }, "devDependencies": { "@babel/cli": "7.27.0", @@ -3683,6 +3684,15 @@ "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==" }, + "node_modules/@zod/core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@zod/core/-/core-0.3.3.tgz", + "integrity": "sha512-zXp0/K9zynk8ZP5hdUN2i0xePJ6uULX5rvBC/54bWNF4FL9YHxTjQg/zPFNj+WE8g0QTKX+fty7n073bgp6wNw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -8748,9 +8758,9 @@ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -11209,6 +11219,20 @@ "version": "3.24.2", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod4": { + "name": "zod", + "version": "4.0.0-beta.20250411T005215", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.0-beta.20250411T005215.tgz", + "integrity": "sha512-FgvuS7Gb0kzI9Rsd1ihOulGSFT9LVj0JdejbkvjXIski9F/DheDIBV9uZkbAIiS6bOsthAMWHFtSsM1o+hmhig==", + "license": "MIT", + "dependencies": { + "@zod/core": "0.3.3" + }, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -13559,6 +13583,11 @@ "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==" }, + "@zod/core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@zod/core/-/core-0.3.3.tgz", + "integrity": "sha512-zXp0/K9zynk8ZP5hdUN2i0xePJ6uULX5rvBC/54bWNF4FL9YHxTjQg/zPFNj+WE8g0QTKX+fty7n073bgp6wNw==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -17074,9 +17103,9 @@ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==" }, "serve": { "version": "14.2.4", @@ -18809,6 +18838,14 @@ "version": "3.24.2", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==" + }, + "zod4": { + "version": "npm:zod@4.0.0-beta.20250411T005215", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.0-beta.20250411T005215.tgz", + "integrity": "sha512-FgvuS7Gb0kzI9Rsd1ihOulGSFT9LVj0JdejbkvjXIski9F/DheDIBV9uZkbAIiS6bOsthAMWHFtSsM1o+hmhig==", + "requires": { + "@zod/core": "0.3.3" + } } } } diff --git a/package.json b/package.json index 70c81a173..e4ff10e0d 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,8 @@ "vega": "5.33.0", "vega-lite": "5.11.0", "yup": "1.6.1", - "zod": "3.24.2" + "zod": "3.24.2", + "zod4": "npm:zod@next" }, "devDependencies": { "@babel/cli": "7.27.0", diff --git a/test/benchmarks.test.ts b/test/benchmarks.test.ts index acfe8bee7..02c9a0242 100644 --- a/test/benchmarks.test.ts +++ b/test/benchmarks.test.ts @@ -58,6 +58,7 @@ import '../cases/valita'; import '../cases/vality'; import '../cases/yup'; import '../cases/zod'; +import '../cases/zod4'; import '../cases/deepkit'; import '../cases/effect-schema'; import '../cases/ts-auto-guard';