如何使用Zod创建含必填键的Record类型?
如何用Zod创建含必填键的Record类型
要实现包含所有指定必填键、值类型统一的Zod Schema,不能直接用z.record(因为它会生成带可选键的Partial类型),可以通过以下两种方式解决:
方法一:用z.object动态生成形状(推荐)
利用枚举的options属性获取所有键,动态构建z.object需要的形状,生成的Schema会自动推断出所有键必填的类型:
import { z } from "zod"; const KeysSchema = z.enum(['a', 'b', 'c']); // 长键列表 // 动态生成对象形状:每个键对应值类型为z.number() const requiredObjShape = Object.fromEntries( KeysSchema.options.map(key => [key, z.number()]) ) as const; const ObjSchema = z.object(requiredObjShape); // 推断出的类型:{ a: number; b: number; c: number; } type MyObj = z.infer<typeof ObjSchema>;
验证效果
- 合法输入:
ObjSchema.parse({ a: 1, b: 2, c: 3 })→ 正常通过 - 非法输入(缺少键):
ObjSchema.parse({ a: 1 })→ 抛出Zod验证错误,提示缺少b和c
方法二:结合z.record与refine(适合特殊场景)
如果必须基于z.record扩展,可以通过refine添加自定义校验,同时手动指定推断类型:
import { z } from "zod"; const KeysSchema = z.enum(['a', 'b', 'c']); type RequiredKeys = z.infer<typeof KeysSchema>[number]; type MyObj = Record<RequiredKeys, number>; const ObjSchema = z.record(KeysSchema, z.number()) .refine(obj => { // 校验所有必填键是否存在 return KeysSchema.options.every(key => key in obj); }, { message: "必须包含所有指定的键" }) as z.ZodType<MyObj>; // 手动断言为必填类型
注意事项
这种方法需要手动做类型断言,不如方法一直接,仅推荐在无法使用z.object的特殊场景下使用。
为什么z.record会生成可选类型?
Zod的z.record设计初衷是允许对象包含枚举中任意子集的键(甚至没有键),因此TypeScript推断出的类型是Partial<Record<Keys, Value>>,这和“所有键必须存在”的需求不匹配,因此需要改用z.object来实现必填键的约束。
内容的提问来源于stack exchange,提问作者Alex Wayne
相关产品推荐
相关产品推荐

