如何在Zod中创建Partial Record实现TypeScript运行时类型解析?
在TypeScript中使用Zod创建Partial Record实现运行时类型解析
你需要用Zod创建支持运行时校验的Partial Record类型,避免编译时正常但运行时因访问未定义属性报错的问题。
原代码存在的问题:
const ZodRecord = z.record(z.string(), z.string()) type ZodRecord = z.infer<typeof ZodRecord> const zodRecord: ZodRecord = { foo: 'foo', } console.log(zodRecord.foo.toUpperCase()) console.log(zodRecord.bar.toUpperCase()) // 编译时无提示,运行时抛出TypeError
这段代码在编译阶段和编辑器中不会报错,但运行时访问zodRecord.bar会因undefined无法调用toUpperCase()抛出错误。
你已经知道TypeScript内置类型可以实现编译时防护:
type PartialRecord = Partial<Record<string, string>> const partialRecord: PartialRecord = { foo: 'foo', } // console.log(partialRecord.foo.toUpperCase()) 编译时提示:partialRecord.foo is possibly 'undefined'
但需要在Zod中实现同样的效果,且因为键是运行时动态生成的,必须使用Record类型而非Zod Object的.partial()方法。
解决方案
要在Zod中创建Partial Record,只需将Record的值schema标记为可选(optional()):
import { z } from 'zod'; // 定义Zod Partial Record schema const ZodPartialRecord = z.record(z.string(), z.string().optional()); // 推导对应的TypeScript类型 type ZodPartialRecord = z.infer<typeof ZodPartialRecord>; // 使用示例 const partialRecord: ZodPartialRecord = { foo: 'foo', }; // 编译阶段会提示:partialRecord.foo is possibly 'undefined' // console.log(partialRecord.foo.toUpperCase()); // 正确用法:先判断属性是否存在 if (partialRecord.foo) { console.log(partialRecord.foo.toUpperCase()); // 运行时安全 } // 运行时校验示例 const invalidData = { bar: 123 }; const result = ZodPartialRecord.safeParse(invalidData); console.log(result.success); // false,因为bar的值不是string或undefined
原理说明
- Zod的
z.record(keySchema, valueSchema)中,将valueSchema改为z.string().optional()后,生成的类型等价于Partial<Record<string, string>>,TypeScript会自动提示属性可能为undefined。 - 运行时Zod会校验所有存在的键对应的值必须是string类型,不存在的键则允许访问但TypeScript会做编译时防护,避免运行时错误。
内容的提问来源于stack exchange,提问作者Nyfiken Gul
相关产品推荐
相关产品推荐

