or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-schemas.mdcoercion.mdcollections.mderrors.mdindex.mdiso-datetime.mdjson-schema.mdlocales.mdnumber-formats.mdparsing.mdprimitives.mdrefinements.mdstring-formats.mdtransformations.mdunions-intersections.mdutilities.mdwrappers.md

advanced-schemas.mddocs/

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