如何用Zod为TypeScript类型创建Schema及扩展外部类型?
Zod 常见问题解答:类型到Schema的转换与外部类型集成
1. 如何使用Zod为任意TypeScript类型创建Schema?
Zod提供了直观的API来映射不同的TypeScript类型,以下是常见场景的实现方式:
- 基础类型:直接使用Zod内置的对应方法,比如
z.string()对应string,z.number()对应number,z.boolean()对应boolean等。 - 联合类型/字面量类型:用
z.union()组合多个字面量schema,或者更简洁的z.enum:
type Status = "pending" | "success" | "failed"; // 方式1:union + literal const statusSchema = z.union([z.literal("pending"), z.literal("success"), z.literal("failed")]); // 方式2:直接用enum const statusSchema = z.enum(["pending", "success", "failed"]);
- 对象接口/类型别名:用
z.object()定义结构,嵌套对应字段的schema:
interface User { name: string; age: number; isActive: boolean; } const userSchema = z.object({ name: z.string(), age: z.number().min(18), isActive: z.boolean() }); // 也可以从schema反向推导类型:type User = z.infer<typeof userSchema>
- 复杂集合类型:结合
z.array()、z.record()、z.tuple()等方法处理数组、记录、元组:
type UserList = User[]; const userListSchema = z.array(userSchema); type UserMap = Record<string, User>; const userMapSchema = z.record(z.string(), userSchema);
2. 如何将Zod的类型系统与外部接口/类型进行扩展?
你用z.custom<MyType>()未达预期,核心原因是**z.custom默认仅做TypeScript层面的类型断言,没有运行时校验逻辑**——Zod无法自动识别外部类型的结构,必须手动补充验证规则。以下是几种可靠的解决方案:
方案1:为z.custom添加运行时校验逻辑
如果清楚MyType的运行时特征,在z.custom中传入验证函数,确保数据符合类型要求:
import * as z from 'zod' import { MyType } from './myType' // 假设MyType是包含id(数字)和name(字符串)的对象 const mySchema = z.object({ custom: z.custom<MyType>((val) => { return typeof val === 'object' && val !== null && 'id' in val && typeof val.id === 'number' && 'name' in val && typeof val.name === 'string'; }, { message: "输入不符合MyType的结构要求" // 自定义错误提示 }) })
方案2:基于外部类型结构构建匹配的Zod Schema
如果MyType是接口或类型别名,直接用Zod的基础API拼接出对应schema,还可以通过类型断言确保编译时类型一致:
import * as z from 'zod' import { MyType } from './myType' // 按照MyType的字段定义对应的schema const myTypeSchema = z.object({ foo: z.string(), bar: z.number().positive() }) // 编译时校验:确保schema推导的类型与MyType匹配(不匹配则报错) type _AssertMatch = z.infer<typeof myTypeSchema> extends MyType ? true : never; const mySchema = z.object({ custom: myTypeSchema })
方案3:类类型用z.instanceof
如果MyType是Class(而非接口/类型别名),直接使用z.instanceof即可:
import * as z from 'zod' import { MyType } from './myType' // 这里MyType是类 const mySchema = z.object({ custom: z.instanceof(MyType) })
方案4:用z.refine做类型窄化
如果已有一个基础schema,需要将其窄化为外部类型,可使用z.refine配合类型谓词:
import * as z from 'zod' import { MyType } from './myType' const mySchema = z.object({ custom: z.any().refine((val): val is MyType => { // 这里编写验证逻辑,返回true则Zod会将val的类型断言为MyType return /* 验证val符合MyType结构的逻辑 */; }) })
内容的提问来源于stack exchange,提问作者Mayro Myller
相关产品推荐
相关产品推荐

