0
# Type Inference and Utilities
1
2
Extract TypeScript types from schemas and utilities for schema manipulation.
3
4
## Type Inference
5
6
```typescript { .api }
7
// Output type (after transformations)
8
type infer<T extends ZodType> = T["_output"];
9
type output<T extends ZodType> = T["_output"];
10
11
// Input type (before transformations)
12
type input<T extends ZodType> = T["_input"];
13
```
14
15
**Examples:**
16
```typescript
17
const UserSchema = z.object({
18
name: z.string(),
19
age: z.number(),
20
});
21
22
type User = z.infer<typeof UserSchema>;
23
// { name: string; age: number }
24
25
type UserInput = z.input<typeof UserSchema>;
26
// Same as output for simple schemas
27
28
// With transformation
29
const TransformSchema = z.string().transform((s) => s.length);
30
31
type Input = z.input<typeof TransformSchema>; // string
32
type Output = z.output<typeof TransformSchema>; // number
33
type Inferred = z.infer<typeof TransformSchema>; // number (same as output)
34
```
35
36
## Schema Cloning
37
38
```typescript { .api }
39
function clone<T extends ZodTypeAny>(
40
schema: T,
41
def?: Partial<T["_def"]>,
42
params?: { parent?: boolean }
43
): T;
44
```
45
46
**Examples:**
47
```typescript
48
const original = z.string();
49
const cloned = z.clone(original);
50
51
// Clone with modifications
52
const modified = z.clone(original, {
53
description: "New description",
54
});
55
```
56
57
## Configuration
58
59
```typescript { .api }
60
function config(options?: Partial<ZodConfig>): ZodConfig;
61
62
interface ZodConfig {
63
locale?: Locale;
64
errorMap?: ZodErrorMap;
65
}
66
```
67
68
**Examples:**
69
```typescript
70
// Global error map
71
z.config({
72
errorMap: (issue, ctx) => {
73
if (issue.code === z.ZodIssueCode.invalid_type) {
74
return { message: "Custom type error message" };
75
}
76
return { message: ctx.defaultError };
77
},
78
});
79
80
// Global locale
81
z.config({
82
locale: z.locales.es(),
83
});
84
85
// Combined
86
z.config({
87
locale: z.locales.fr(),
88
errorMap: customErrorMap,
89
});
90
```
91
92
## Schema Utilities
93
94
```typescript
95
// Check schema type
96
schema instanceof z.ZodString
97
schema instanceof z.ZodNumber
98
schema instanceof z.ZodObject
99
100
// Get schema _def
101
schema._def
102
103
// Schema methods available on all types
104
schema.optional()
105
schema.nullable()
106
schema.default(value)
107
schema.catch(fallback)
108
schema.refine(fn, msg)
109
schema.transform(fn)
110
schema.parse(data)
111
schema.safeParse(data)
112
```
113
114
## Type Guards and Helpers
115
116
```typescript
117
// Type narrowing with safeParse
118
const result = schema.safeParse(data);
119
120
if (result.success) {
121
// result.data is typed correctly
122
const validData: OutputType = result.data;
123
} else {
124
// result.error is ZodError
125
const error: z.ZodError = result.error;
126
}
127
128
// Extract object shape
129
const UserSchema = z.object({
130
name: z.string(),
131
age: z.number(),
132
});
133
134
type UserShape = typeof UserSchema.shape;
135
// { name: ZodString; age: ZodNumber }
136
137
// Extract enum options
138
const StatusSchema = z.enum(["pending", "active", "completed"]);
139
type StatusOptions = typeof StatusSchema.options;
140
// ["pending", "active", "completed"]
141
142
const statusEnum = StatusSchema.enum;
143
// { pending: "pending", active: "active", completed: "completed" }
144
```
145
146
## Common Patterns
147
148
```typescript
149
// Reusable type inference
150
const createSchema = () => z.object({
151
id: z.string(),
152
name: z.string(),
153
});
154
155
type InferredType = z.infer<ReturnType<typeof createSchema>>;
156
157
// Generic schema function
158
function createAPISchema<T extends z.ZodTypeAny>(dataSchema: T) {
159
return z.object({
160
success: z.boolean(),
161
data: dataSchema,
162
error: z.string().optional(),
163
});
164
}
165
166
const UserAPISchema = createAPISchema(UserSchema);
167
type UserAPIResponse = z.infer<typeof UserAPISchema>;
168
169
// Extract nested types
170
const NestedSchema = z.object({
171
user: z.object({
172
profile: z.object({
173
name: z.string(),
174
}),
175
}),
176
});
177
178
type Nested = z.infer<typeof NestedSchema>;
179
type User = Nested["user"];
180
type Profile = Nested["user"]["profile"];
181
182
// Conditional schema creation
183
function createSchemaWithOptional<T extends boolean>(
184
includeOptional: T
185
): T extends true
186
? z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }>
187
: z.ZodObject<{ name: z.ZodString }> {
188
// Implementation
189
}
190
191
// Branded types
192
type UserId = z.infer<typeof z.string()> & { readonly __brand: unique symbol };
193
194
const UserIdSchema = z.string().refine(
195
(val): val is UserId => /^user_/.test(val)
196
);
197
```
198
199
## Advanced Type Inference
200
201
```typescript
202
// Infer from pipe
203
const PipeSchema = z.pipe(z.string(), z.number());
204
type PipeInput = z.input<typeof PipeSchema>; // string
205
type PipeOutput = z.output<typeof PipeSchema>; // number
206
207
// Infer from union
208
const UnionSchema = z.union([
209
z.object({ type: z.literal("a"), value: z.string() }),
210
z.object({ type: z.literal("b"), value: z.number() }),
211
]);
212
213
type Union = z.infer<typeof UnionSchema>;
214
// { type: "a"; value: string } | { type: "b"; value: number }
215
216
// Infer from discriminated union
217
const DiscriminatedSchema = z.discriminatedUnion("type", [
218
z.object({ type: z.literal("success"), data: z.any() }),
219
z.object({ type: z.literal("error"), error: z.string() }),
220
]);
221
222
type Result = z.infer<typeof DiscriminatedSchema>;
223
224
// Recursive type inference
225
interface Category {
226
name: string;
227
children: Category[];
228
}
229
230
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
231
z.object({
232
name: z.string(),
233
children: z.array(CategorySchema),
234
})
235
);
236
237
type InferredCategory = z.infer<typeof CategorySchema>; // Category
238
```
239
240
## Utility Types
241
242
```typescript
243
// Partial object schema
244
type PartialUser = z.infer<typeof UserSchema.partial()>;
245
246
// Pick from object
247
type UserNameEmail = z.infer<typeof UserSchema.pick({ name: true, email: true })>;
248
249
// Omit from object
250
type UserWithoutPassword = z.infer<typeof UserSchema.omit({ password: true })>;
251
252
// Extended schema
253
type ExtendedUser = z.infer<typeof UserSchema.extend({ role: z.string() })>;
254
255
// Merged schema
256
type MergedUser = z.infer<typeof UserSchema.merge(ProfileSchema)>;
257
258
// Array element type
259
const ArraySchema = z.array(z.string());
260
type Element = z.infer<typeof ArraySchema>[number]; // string
261
262
// Object key type
263
const ObjSchema = z.object({ a: z.string(), b: z.number() });
264
type Keys = keyof z.infer<typeof ObjSchema>; // "a" | "b"
265
```
266