Skip to content

Commit f67332f

Browse files
committed
Docs
1 parent 32104c2 commit f67332f

File tree

4 files changed

+45
-71
lines changed

4 files changed

+45
-71
lines changed

packages/docs/content/api.mdx

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ colors.values; // => Set<"red" | "green" | "blue">
123123
</Tab>
124124
</Tabs>
125125

126+
127+
126128
## Strings
127129

128130
{/* Zod provides a handful of built-in string validation and transform APIs.
@@ -449,6 +451,36 @@ const cidrv6 = z.string().cidrv6();
449451
cidrv6.parse("2001:db8::/32"); //
450452
```
451453

454+
## Template literals
455+
456+
> **New in Zod 4**
457+
458+
To define a template literal schema:
459+
460+
```ts
461+
const schema = z.templateLiteral("hello, ", z.string(), "!");
462+
// `hello, ${string}!`
463+
```
464+
465+
The `z.templateLiteral` API can handle any number of string literals (e.g. `"hello"`) and schemas. Any schema with an inferred type that's assignable to `string | number | bigint | boolean | null | undefined` can be passed.
466+
467+
```ts
468+
z.templateLiteral([ "hi there" ]);
469+
// `hi there`
470+
471+
z.templateLiteral([ "email: ", z.string() ]);
472+
// `email: ${string}`
473+
474+
z.templateLiteral([ "high", z.literal(5) ]);
475+
// `high5`
476+
477+
z.templateLiteral([ z.nullable(z.literal("grassy")) ]);
478+
// `grassy` | `null`
479+
480+
z.templateLiteral([ z.number(), z.enum(["px", "em", "rem"]) ]);
481+
// `${number}px` | `${number}em` | `${number}rem`
482+
```
483+
452484
## Numbers
453485

454486
Use `z.number()` to validate numbers. It allows any finite number.
@@ -703,7 +735,7 @@ const SalmonAndTroutOnly = FishEnum.extract(["Salmon", "Trout"]);
703735
</Tab>
704736
</Tabs>
705737

706-
## Stringbool
738+
## Stringbools [#stringbool]
707739

708740
> **💎 New in Zod 4**
709741
@@ -747,6 +779,7 @@ z.stringbool({
747779
});
748780
```
749781

782+
750783
## Optionals
751784

752785
To make a schema *optional* (that is, to allow `undefined` inputs).
@@ -848,29 +881,6 @@ No value will pass validation.
848881
z.never(); // inferred type: `never`
849882
```
850883

851-
## Template literals
852-
853-
854-
> **💎 New in Zod 4**
855-
856-
Zod 4 finally implements one of the last remaining unrepresented features of TypeScript's type system: template literals. Virtually all primitive schemas can be used in `z.templateLiteral`: strings, string formats like `z.email()`, numbers, booleans, enums, literals (of the non-template variety), optional/nullable, and other template literals.
857-
858-
```ts
859-
const hello = z.templateLiteral(["hello, ", z.string()]);
860-
// `hello, ${string}`
861-
862-
const cssUnits = z.enum(["px", "em", "rem", "%"]);
863-
const css = z.templateLiteral([z.number(), cssUnits]);
864-
// `${number}px` | `${number}em` | `${number}rem` | `${number}%`
865-
866-
const email = z.templateLiteral([
867-
z.string().min(1),
868-
"@",
869-
z.string().max(64),
870-
]);
871-
// `${string}@${string}` (the min/max refinements are enforced!)
872-
```
873-
874884
## Objects
875885

876886
To define an object type:
@@ -1022,7 +1032,7 @@ const DogWithBreed = z.extend(Dog, {
10221032
This API can be used to overwrite existing fields! Be careful with this power! If the two schemas share keys, B will override A.
10231033
</Callout>
10241034

1025-
Despite the existence of the `.extend` API, the recommended way to extend an object schema is to create an entirely new schema:
1035+
Despite the existence of the `.extend` API, the recommended way to extend an object schema is to create an entirely new schema by destructuring the original schema's `shape` property.
10261036

10271037
```ts
10281038
const DogWithBreed = z.object({
@@ -2397,7 +2407,7 @@ type ReadonlyUser = z.infer<typeof ReadonlyUser>;
23972407
</Tab>
23982408
</Tabs>
23992409

2400-
This returns a new schema that wraps the original. The new schema's inferred type will be marked as `readonly`. Note that this only affects objects, arrays, tuples, `Set`, and `Map` in TypeScript:
2410+
The inferred type of the new schemas will be marked as `readonly`. Note that in TypeScript, this only affects objects, arrays, tuples, `Set`, and `Map`:
24012411

24022412
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
24032413
<Tab value="Zod">
@@ -2420,7 +2430,7 @@ z.readonly(z.set(z.string())); // ReadonlySet<string>
24202430
</Tab>
24212431
</Tabs>
24222432

2423-
Inputs will be parsed using the original schema, then the result will be frozen with [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) to prevent modifications.
2433+
Inputs will be parsed like normal, then the result will be frozen with [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) to prevent modifications.
24242434

24252435
<Tabs groupId="lib" items={["Zod", "Zod Mini"]}>
24262436
<Tab value="Zod">
@@ -2437,36 +2447,6 @@ result.name = "simba"; // throws TypeError
24372447
</Tab>
24382448
</Tabs>
24392449

2440-
## Template literals
2441-
2442-
> **New in Zod 4**
2443-
2444-
To define a template literal schema:
2445-
2446-
```ts
2447-
const schema = z.templateLiteral("hello, ", z.string(), "!");
2448-
// `hello, ${string}!`
2449-
```
2450-
2451-
The `z.templateLiteral` API can handle any number of string literals (e.g. `"hello"`) and schemas. Any schema with an inferred type that's assignable to `string | number | bigint | boolean | null | undefined` can be passed.
2452-
2453-
```ts
2454-
z.templateLiteral([ "hi there" ]);
2455-
// `hi there`
2456-
2457-
z.templateLiteral([ "email: ", z.string() ]);
2458-
// `email: ${string}`
2459-
2460-
z.templateLiteral([ "high", z.literal(5) ]);
2461-
// `high5`
2462-
2463-
z.templateLiteral([ z.nullable(z.literal("grassy")) ]);
2464-
// `grassy` | `null`
2465-
2466-
z.templateLiteral([ z.number(), z.enum(["px", "em", "rem"]) ]);
2467-
// `${number}px` | `${number}em` | `${number}rem`
2468-
```
2469-
24702450
## JSON
24712451

24722452
To validate any JSON-encodable value:

packages/zod/src/v4/classic/schemas.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,12 +1152,10 @@ export function strictObject<T extends core.$ZodLooseShape>(
11521152
): ZodObject<T, core.$strict> {
11531153
return new ZodObject({
11541154
type: "object",
1155-
11561155
get shape() {
11571156
util.assignProp(this, "shape", { ...shape });
11581157
return this.shape;
11591158
},
1160-
11611159
catchall: never(),
11621160
...util.normalizeParams(params),
11631161
}) as any;
@@ -1171,12 +1169,10 @@ export function looseObject<T extends core.$ZodLooseShape>(
11711169
): ZodObject<T, core.$loose> {
11721170
return new ZodObject({
11731171
type: "object",
1174-
11751172
get shape() {
11761173
util.assignProp(this, "shape", { ...shape });
11771174
return this.shape;
11781175
},
1179-
11801176
catchall: unknown(),
11811177
...util.normalizeParams(params),
11821178
}) as any;

packages/zod/src/v4/classic/tests/generics.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,5 @@ test("generic on output type", () => {
6868
schema: z.object({
6969
name: z.string(),
7070
}),
71-
})._zod.output.name;
71+
})?._zod?.output?.name;
7272
});

play.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22

3-
// (A) fails in v4 – TDZ on recursive use
4-
const NodeA: z.ZodType<any> = z.lazy(() => NodeA).optional();
3+
const A = z.object({
4+
get x() {
5+
return A;
6+
},
7+
});
58

6-
// (B) works in v4
7-
const NodeB: z.ZodType<any> = z.lazy(() => NodeB.optional());
8-
9-
// Usage
10-
NodeA.parse(undefined); // ❌ ReferenceError: Cannot access 'NodeA' before initialization
11-
NodeB.parse(undefined); // ✅ passes
9+
const StrictA = A.strict();

0 commit comments

Comments
 (0)