0
# Advanced Schemas
1
2
Schemas for functions, promises, custom validation, file uploads, and recursive structures.
3
4
## Function Schema
5
6
```typescript { .api }
7
function function<
8
Args extends ZodTuple<any, any> = ZodTuple<[], ZodUnknown>,
9
Returns extends ZodTypeAny = ZodUnknown
10
>(params?: { description?: string; errorMap?: ZodErrorMap }): ZodFunction<Args, Returns>;
11
12
interface ZodFunction<Args, Returns> {
13
args<T extends ZodTuple<any, any>>(...schemas: T): ZodFunction<T, Returns>;
14
returns<T extends ZodTypeAny>(schema: T): ZodFunction<Args, T>;
15
implement(fn: (...args: any[]) => any): (...args: any[]) => any;
16
}
17
```
18
19
**Examples:**
20
```typescript
21
// Basic function
22
const fn = z.function();
23
24
// With arguments
25
const fn = z.function()
26
.args(z.string(), z.number())
27
.returns(z.boolean());
28
29
// Implementation
30
const safeFunction = z
31
.function()
32
.args(z.string(), z.number())
33
.returns(z.string())
34
.implement((name, age) => `${name} is ${age} years old`);
35
36
// Validates at runtime
37
safeFunction("Alice", 25); // OK
38
safeFunction(123, "invalid"); // Throws
39
```
40
41
## Promise Schema
42
43
```typescript { .api }
44
function promise<T extends ZodTypeAny>(schema: T): ZodPromise<T>;
45
```
46
47
**Examples:**
48
```typescript
49
z.promise(z.string())
50
z.promise(z.object({ data: z.any() }))
51
52
const PromiseSchema = z.promise(z.number());
53
await PromiseSchema.parseAsync(Promise.resolve(42)); // 42
54
```
55
56
## Lazy Schema (Recursive)
57
58
```typescript { .api }
59
function lazy<T extends ZodTypeAny>(getter: () => T): ZodLazy<T>;
60
```
61
62
**Examples:**
63
```typescript
64
// Recursive type
65
interface Category {
66
name: string;
67
children: Category[];
68
}
69
70
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
71
z.object({
72
name: z.string(),
73
children: z.array(CategorySchema),
74
})
75
);
76
77
// Tree structure
78
interface Node {
79
value: number;
80
left?: Node;
81
right?: Node;
82
}
83
84
const NodeSchema: z.ZodType<Node> = z.lazy(() =>
85
z.object({
86
value: z.number(),
87
left: NodeSchema.optional(),
88
right: NodeSchema.optional(),
89
})
90
);
91
92
// Linked list
93
interface ListNode {
94
value: string;
95
next?: ListNode;
96
}
97
98
const ListNodeSchema: z.ZodType<ListNode> = z.lazy(() =>
99
z.object({
100
value: z.string(),
101
next: ListNodeSchema.optional(),
102
})
103
);
104
```
105
106
## Custom Schema
107
108
```typescript { .api }
109
function custom<T = any>(
110
check?: (data: unknown) => boolean,
111
params?: { fatal?: boolean; description?: string; errorMap?: ZodErrorMap }
112
): ZodCustom<T>;
113
```
114
115
**Examples:**
116
```typescript
117
// Basic custom validation
118
const CustomSchema = z.custom<string>((val) => typeof val === "string");
119
120
// With validation logic
121
const EvenNumber = z.custom<number>((val) => {
122
return typeof val === "number" && val % 2 === 0;
123
});
124
125
// Custom type
126
const PositiveNumber = z.custom<number>((val) => {
127
return typeof val === "number" && val > 0;
128
}, { description: "Must be positive number" });
129
```
130
131
## InstanceOf
132
133
```typescript { .api }
134
function instanceof<T extends new (...args: any[]) => any>(
135
cls: T,
136
params?: { description?: string; errorMap?: ZodErrorMap }
137
): ZodCustom<InstanceType<T>>;
138
```
139
140
**Examples:**
141
```typescript
142
z.instanceof(Date)
143
z.instanceof(Error)
144
z.instanceof(RegExp)
145
146
class MyClass {}
147
z.instanceof(MyClass)
148
149
// In schema
150
const schema = z.object({
151
createdAt: z.instanceof(Date),
152
error: z.instanceof(Error).optional(),
153
});
154
```
155
156
## File Schema
157
158
```typescript { .api }
159
function file(params?: { description?: string; errorMap?: ZodErrorMap }): ZodFile;
160
161
interface ZodFile {
162
minSize(bytes: number, msg?: string | { message?: string }): this;
163
maxSize(bytes: number, msg?: string | { message?: string }): this;
164
type(mimeTypes: string | string[], msg?: string | { message?: string }): this;
165
}
166
```
167
168
**Examples:**
169
```typescript
170
// Basic file
171
z.file()
172
173
// File with constraints
174
z.file()
175
.minSize(1024) // 1KB minimum
176
.maxSize(5242880) // 5MB maximum
177
.type("image/jpeg") // JPEG only
178
179
// Multiple mime types
180
z.file().type(["image/jpeg", "image/png", "image/gif"])
181
182
// Form with file upload
183
const FormSchema = z.object({
184
name: z.string(),
185
avatar: z.file()
186
.maxSize(2097152) // 2MB
187
.type(["image/jpeg", "image/png"]),
188
});
189
```
190
191
## Common Patterns
192
193
```typescript
194
// Validated callback
195
const CallbackSchema = z
196
.function()
197
.args(z.string(), z.number())
198
.returns(z.void());
199
200
// API that returns promise
201
const APISchema = z.promise(z.object({
202
data: z.array(z.any()),
203
total: z.number(),
204
}));
205
206
// Recursive menu
207
interface MenuItem {
208
label: string;
209
items?: MenuItem[];
210
}
211
212
const MenuSchema: z.ZodType<MenuItem> = z.lazy(() =>
213
z.object({
214
label: z.string(),
215
items: z.array(MenuSchema).optional(),
216
})
217
);
218
219
// File upload validation
220
const UploadSchema = z.object({
221
document: z.file()
222
.maxSize(10485760) // 10MB
223
.type(["application/pdf"]),
224
images: z.array(z.file()
225
.maxSize(5242880) // 5MB per image
226
.type(["image/jpeg", "image/png"])
227
).max(5),
228
});
229
230
// Custom branded type
231
const UserId = z.custom<string & { __brand: "UserId" }>((val) => {
232
return typeof val === "string" && /^user_/.test(val);
233
});
234
```
235