如何在 Zod 中以编程方式映射对象值?

How does one programatically map object values in Zod?

提问人:stealing_society 提问时间:11/17/2023 最后编辑:stealing_society 更新时间:11/17/2023 访问量:29

问:

对于以下架构:

const z_BaseCustomer = z.object({
  name: z.string(),
  age: z.number()
});

const pizzas = [
  {
    value: "pn_pizza",
    label: "Pineapple Pizza",
  },
  {
    value: "vgt_pizza",
    label: "Vegetarian Pizza",
  },
  {
    value: "sc_pizza",
    label: "Sicilian Pizza"
  },
  {
    value: "mg_pizza",
    label: "Pizza Margherita"
  },
  {
    value: "ny_pizza",
    label: "New York-Style Pizza"
  }
] as const;

type FavoritePizzaValue = typeof pizzas[number]['value'];
type FavoritePizzaLabel = typeof pizzas[number]['label'];
const z_FavoritePizzaValue = z.custom<FavoritePizzaValue>;
const z_FavoritePizzaLabel = z.custom<FavoritePizzaLabel>;

const drinks = [
  {
    value: "dr_cola",
    label: "Coca Cola"
  },
  {
    value: "dr_mtdew",
    label: "Mountain Dew"
  }
] as const;

type FavoriteDrinkValue = typeof drinks[number]['value'];
type FavoriteDrinkLabel = typeof drinks[number]['label'];
const z_FavoriteDrinkValue = z.custom<FavoriteDrinkValue>;
const z_FavoriteDrinkLabel = z.custom<FavoriteDrinkLabel>;


const z_ServerCustomer = z_BaseCustomer.extend({
  favorite_pizza: z_FavoritePizzaValue(),
  favorite_drink: z_FavoriteDrinkValue()
});

const z_ClientCustomer = z_BaseCustomer.extend({
  favorite_pizza: z_FavoritePizzaLabel(),
  favorite_drink: z_FavoriteDrinkLabel()
});

type ServerCustomer = z.infer<typeof z_ServerCustomer>;
type ClientCustomer = z.infer<typeof z_ClientCustomer>;

我的目标是将这两种类型的对象相互映射,以便将数据存储在我的数据库中并在浏览器中呈现。ServerCustomerClientCustomer

有没有比只是更好的方法..?:

const CustomerUnionSchema = z.discriminatedUnion("favorite_pizza", [
  z_ServerCustomer, z_ClientCustomer
]).transform(customer => {
  const ret = {
    name: customer.name,
    age: customer.age,
  }
  for(var i in pizzas){
    customer.favorite_pizza === pizzas[i].value
    ? ret.favorite_pizza = pizzas[i].label
    : ret.favorite_pizza = pizzas[i].value
  }
  for(var i in drinks){
    customer.favorite_drink === drinks[i].value
    ? ret.favorite_drink = drinks[i].label
    : ret.favorite_drink = drinks[i].value
  }
  return ret;
});

搜索 Zod 文档一无所获,此处相同。Zod 有没有办法推断这些类型的映射?此外,我是否应该改变输入数据的方法?什么被认为是最好的?

JavaScript TypeScript 类型转换 Zod

评论

0赞 Bergi 11/17/2023
不要用于...在数组的枚举中,并且不要滥用语句的条件运算符!if
0赞 Bergi 11/17/2023
您最喜欢使用映射对象 ( 或 ),而不是元组数组。通过映射,还可以推断类型。satisfies Record<FavoritePizzaValue, FavoritePizzaLabel>Map<FavoritePizzaValue, FavoritePizzaLabel>as const
0赞 Bergi 11/17/2023
中的代码似乎不起作用。你到底想让它做什么?如果要将这两种类型相互映射,则应具有两个函数,一个用于向外映射,另一个用于向后映射。你可能应该为此声明正常函数,而不是使用 zod。工会对我来说真的没有意义。transform

答: 暂无答案