You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:07:31