
本文介绍如何借助 zod 库在运行时严格校验 javascript 对象是否符合 typescript 接口定义的结构,实现类型安全的输入验证与数据解析。
本文介绍如何借助 zod 库在运行时严格校验 javascript 对象是否符合 typescript 接口定义的结构,实现类型安全的输入验证与数据解析。
Zod 是一个以零依赖、类型优先为理念的运行时验证库,它不仅能生成精确的 TypeScript 类型,还能在运行时对任意对象进行结构和值的双重校验。当你定义了如 interface f { tmp: number } 这样的静态类型时,Zod 可将其映射为可执行的验证逻辑,从而桥接编译期类型与运行时数据之间的鸿沟。
基础用法:手动构建对应 Schema
最直观的方式是根据接口字段,显式创建 Zod schema:
import { z, ZodError } from "zod";
interface f {
tmp: number;
}
// 手动声明 schema,与 interface 保持语义一致
const schema = z.object({
tmp: z.number(),
});
const myObject = { tmp: 123 };
try {
const validatedObject: f = schema.parse(myObject); // ✅ 成功返回并推导出类型 f
console.log("Object is valid:", validatedObject);
} catch (error) {
if (error instanceof ZodError) {
console.error("Validation failed:", error.issues); // 推荐使用 .issues(.errors 已废弃)
} else {
throw error;
}
}
✅ 注意:
schema.parse()返回值自动具备f类型(得益于 Zod 的类型推导),无需额外断言;若校验失败则抛出ZodError,其.issues属性提供结构化错误信息(如路径、期望类型、实际值等)。
进阶技巧:从接口自动生成 Schema(减少重复)
为避免手动维护 schema 与 interface 的一致性(尤其在字段增多时易出错),可利用 TypeScript 的类型反射能力 + Zod 的 z.object() 灵活性,实现“接口驱动”的 schema 构建:
import { z, ZodError } from "zod";
interface f {
tmp: number;
name?: string;
active: boolean;
}
// 动态构建 schema —— 字段名与类型均来自 interface 定义
const schema = z.object({
tmp: z.number(),
name: z.string().optional(), // 注意:TS 中 ? 对应 .optional()
active: z.boolean(),
} satisfies Record<keyof f z.zodtypeany>);
const myObject = { tmp: 42, active: true };
try {
const validatedObject: f = schema.parse(myObject);
console.log("Validated:", validatedObject); // { tmp: 42, active: true }
} catch (error) {
if (error instanceof ZodError) {
console.error("Errors:", error.issues);
}
}</keyof>
⚠️ 重要说明:
- TypeScript 接口本身无法被运行时读取,因此不存在真正的“自动推导”(如
z.infer<typeof f></typeof>不合法)。所谓“自动”,实为开发者通过类型约束(如satisfies)+ 显式声明保障一致性; - 若需更高阶自动化(如基于装饰器或代码生成),可结合
zod-to-json-schema或构建时工具(如zod-dts),但通常手动维护已足够清晰可控; - 使用
satisfies断言可确保z.object({...})的键集与keyof f完全匹配,配合 TS 编译器报错即时发现遗漏字段。
最佳实践总结
- ✅ 始终使用
schema.safeParse()处理不可信输入(如 API 请求体、localStorage 数据),避免异常中断流程; - ✅ 对复杂嵌套接口,善用
z.array()、z.union()、z.record()等组合 schema; - ✅ 在函数入参处封装验证逻辑,形成「守门人」模式:
const handleUserInput = (raw: unknown) => { const result = schema.safeParse(raw); if (!result.success) throw new Error(`Invalid input: ${result.error.message}`); return result.data; // 类型为 f,100% 可信 }; - ✅ 结合
z.infer<typeof schema></typeof>替代手写 interface(推荐单源事实):const schema = z.object({ tmp: z.number() }); type f = z.infer<typeof schema>; // 自动同步,杜绝不一致</typeof>
Zod 不仅让类型验证变得简洁可靠,更将 TypeScript 的设计意图延伸至运行时——每一次 parse() 都是对契约的确认,每一次 safeParse() 都是对健壮性的加固。











