diff --git a/docs/modules/schema-validation.md b/docs/modules/schema-validation.md new file mode 100644 index 00000000..07d3b90a --- /dev/null +++ b/docs/modules/schema-validation.md @@ -0,0 +1,49 @@ +--- +description: Modern alternatives for TypeScript schema validation +--- + +# TypeScript schema validation + +This page contains common, recommended alternatives for TypeScript schema validation. [`valibot`](https://valibot.dev/) and [`zod/mini`](https://zod.dev/packages/mini) are modular, tree-shakable options that both support [Standard Schema](https://standardschema.dev/), allowing them to work with schema-agnostic integrations. + +See [Schema Benchmarks](https://schemabenchmarks.dev/download) to explore other schema validation libraries and compare their bundle sizes and runtime behavior. + +When migrating between schema libraries, verify optionality, empty-string handling, type coercion, unknown object keys, error messages, and synchronous versus asynchronous validation. + +## `valibot` + +Valibot uses a functional API with tree-shakable schema and validation actions. + +```ts +import * as v from 'valibot' + +const personSchema = v.object({ + name: v.pipe(v.string(), v.nonEmpty()), + age: v.pipe(v.number(), v.minValue(0)) +}) + +const person = v.parse(personSchema, input) +``` + +Valibot schemas are required by default; wrap optional fields with `v.optional(...)`. Use `v.nonEmpty()` when empty strings are invalid, and compose further checks with `v.pipe(...)`. `v.parse` is synchronous; use `v.parseAsync` for asynchronous validation. + +Valibot makes transformations explicit (for example, `v.toNumber()`), and `v.object` removes unknown keys. Use `v.looseObject` when those keys need to be preserved. + +## `zod/mini` + +Zod Mini is the tree-shakable, functional API included with Zod 4. Install `zod@^4.0.0` and import the `zod/mini` subpath: + +```ts +import * as z from 'zod/mini' + +const personSchema = z.object({ + name: z.string().check(z.minLength(1)), + age: z.number().check(z.gte(0)) +}) + +const person = personSchema.parse(input) +``` + +Zod Mini schemas are required by default; wrap optional fields with `z.optional(...)`. Its functional checks are passed to the schema with `.check(...)`, while `parse`, `safeParse`, `parseAsync`, and `safeParseAsync` remain schema methods. As with Valibot, `z.object` strips unknown keys by default; use `z.looseObject` to preserve them. + +Zod Mini does not load a default error-message locale. Configure one explicitly, for example with `z.config(z.locales.en())`, when callers depend on English error messages. diff --git a/manifests/preferred.json b/manifests/preferred.json index 495dc852..a47204c9 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -2797,6 +2797,12 @@ "moduleName": "yargs-parser", "replacements": ["util.parseArgs", "mri"], "url": {"type": "e18e", "id": "parseargs"} + }, + "yup": { + "type": "module", + "moduleName": "yup", + "replacements": ["valibot", "zod/mini"], + "url": {"type": "e18e", "id": "schema-validation"} } }, "replacements": { @@ -3669,6 +3675,11 @@ "nodeFeatureId": {"moduleName": "node:util", "exportName": "types"}, "url": {"type": "node", "id": "api/util.html#utiltypes"} }, + "valibot": { + "id": "valibot", + "type": "documented", + "replacementModule": "valibot" + }, "vitest": { "id": "vitest", "type": "documented", @@ -3695,6 +3706,11 @@ "type": "native", "nodeFeatureId": {"moduleName": "node:zlib", "exportName": "gzipSync"}, "url": {"type": "node", "id": "api/zlib.html#zlibgzipsyncbuffer-options"} + }, + "zod/mini": { + "id": "zod/mini", + "type": "documented", + "replacementModule": "zod" } } }