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

无需重复定义键,如何生成带类型提示的对应Record类型Zod Schema?

问题:Zod Schema无法生成字段提示的解决方法

现有如下JSON对象:

const amenities = { 
  "wifi": "Wifi", 
  "tv": "Tv", 
  "steamIron": "Steam iron", 
  "kitchenette": "Kitchenette", 
  "fridge": "Fridge", 
  "airConditioner": "Air conditioner", 
  "fan": "Fan", 
  "gym": "Gym", 
  "pool": "Pool", 
  "parking": "Parking", 
  "lounge": "Lounge", 
  "laundry": "Laundry", 
  "stove": "Stove", 
  "balcony": "Balcony", 
  "microwave": "Microwave", 
  "oven": "Oven", 
  "desk": "Desk", 
  "towels": "Towels", 
  "bedSheets": "Bed sheets", 
  "studyRoom": "Study room", 
  "chair": "Chair", 
  "table": "Table", 
  "elevator": "Elevator", 
  "generator": "Generator", 
  "security": "Security", 
  "cafe": "Cafe", 
  "restaurant": "Restaurant", 
  "housekeeping": "Housekeeping" 
}

需求是创建一个Zod Schema,实现与interface Amenities extends Record<keyof typeof amenities, boolean> {}相同的效果:生成的对象必须包含amenities的所有键,且每个键的值为布尔类型。

曾尝试以下代码:

export const Amenities = z.record(z.boolean()).refine((val) => {
    const keys = Object.keys(amenities);
    for (const key of keys) {
        if (!(key in val)) {
            return false;
        }
    }
    return true;
}, {
    message: 'Amenities should have all keys defined',
}).nonstrict();

但通过该Schema推断类型后,创建对象时无法获得字段提示,请问该如何解决?


解决方案

你之前用z.record()的方式,类型推断会得到Record<string, boolean>,TypeScript无法识别具体的键名,所以不会有字段提示。正确的做法是基于amenities的键生成一个严格的对象Schema,具体实现如下:

import { z } from "zod";

const amenities = { /* 你的amenities对象 */ };

// 生成每个键对应boolean类型的Schema定义
const amenitiesSchemaEntries = Object.keys(amenities).map(key => 
  [key, z.boolean()] as const
);

// 创建严格的对象Schema
export const AmenitiesSchema = z.object(Object.fromEntries(amenitiesSchemaEntries));

// 推断类型,和你需要的interface完全一致
export type Amenities = z.infer<typeof AmenitiesSchema>;

关键说明:

  • Object.keys(amenities).map(...):遍历amenities的所有键,为每个键创建[键名, z.boolean()]的条目,as const用来固定键名的字面量类型,确保TypeScript能识别具体的键。
  • z.object(...):传入生成的条目对象,创建一个严格的对象Schema,要求必须包含所有指定键,且值为布尔类型。
  • 类型推断:通过z.infer<typeof AmenitiesSchema>得到的类型,和你定义的interface Amenities extends Record<keyof typeof amenities, boolean> {}完全一致,创建对象时会自动提示所有字段。

如果需要允许额外的键(类似原代码的.nonstrict()),可以在对象Schema后调用.passthrough():

export const AmenitiesSchema = z.object(
  Object.fromEntries(amenitiesSchemaEntries)
).passthrough();

这样既满足了所有必填键的校验要求,又能获得完整的字段提示。


内容的提问来源于stack exchange,提问作者user21276090

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:45:29