首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Zod联合类型中提取单个类型?

如何从Zod联合类型中提取单个类型?
EN

Stack Overflow用户
提问于 2022-03-01 09:35:17
回答 1查看 3.6K关注 0票数 3

我使用的是佐德,并且有一个数组,其中包含使用友联市的不同对象。解析完后,我想迭代每一项并提取它为“真实”类型/切断其他类型。

在检查特定对象属性时,以下代码工作正常:

代码语言:javascript
复制
const objectWithNumber = zod.object({ num: zod.number() });
const objectWithBoolean = zod.object({ isTruthy: zod.boolean() });
const myArray = zod.array(zod.union([objectWithNumber, objectWithBoolean]));
const parsedArray = myArray.parse([{ isTruthy: true }, { num: 3 }]);

parsedArray.forEach((item) => {
  if ("num" in item) {
    console.info('objectWithNumber:', item);
    // TS knows about it => syntax support for objectWithNumber
  } else if ("isTruthy" in item) {
    console.info('objectWithBoolean:', item);
    // TS knows about it => syntax support for objectWithBoolean
  } else {
    console.error('unknown');
  }
});

另一种选择是使用受歧视的工会来实现

代码语言:javascript
复制
const objectWithNumber = zod.object({ type: zod.literal("objectWithNumber"), num: zod.number() });
const objectWithBoolean = zod.object({ type: zod.literal("objectWithBoolean"), isTruthy: zod.boolean() });
const myArray = zod.array(zod.discriminatedUnion("type", [ objectWithNumber, objectWithBoolean ]));
const parsedArray = myArray.parse([{ type: "objectWithBoolean", isTruthy: true }, { type: "objectWithNumber", num: 3 }]);

parsedArray.forEach(item => {
  if (item.type === "objectWithNumber") {
    console.info('objectWithNumber:', item);
    // TS knows about it => syntax support for objectWithNumber
  } else if (item.type === "objectWithBoolean") {
    console.info('objectWithBoolean:', item);
    // TS knows about it => syntax support for objectWithBoolean
  } else {
    console.error('unknown');
  }
});

但是我想我误解了这个概念,因为需要编写更多的代码(我总是可以添加一个共享属性并检查这个属性)。对此的任何帮助都是非常感谢的:)

是否有更好的方法来识别特定的模式?

EN

回答 1

Stack Overflow用户

发布于 2022-03-09 17:37:18

如果我对您的理解是正确的,那么您的问题归结为“为什么要使用受歧视的联合,而不是将共享字段与可选字段结合起来”。(zod.js只是将这个概念提升到运行时,提供验证功能)。在您的示例中,实际上没有理由使用判别器(type属性),因为每个对象只有一个非可选属性,该属性在类型之间相互排斥,可以很容易地用于区分类型。但是,这个代码的主要问题是对象名称(或形状/结构)不传递任何意图--这就是为什么很难看到受歧视的联合的好处。

您可以将区分联合看作是描述的一种类型,它是一个对象族,并提供了一个统一的机制(以鉴别器属性的形式)来标识它们。这种方法比检查是否存在一些手动选择的属性(例如num属性)更不脆弱。如果num由于任何原因成为可选的,怎么办?那你的存亡支票就会破了。受歧视联合的另一个论点是减少可选属性的数量。比较以下两个例子:

代码语言:javascript
复制
// shared and optional fields instead of discriminated union
type Vehicle = {
  name: string;
  combustionEngine?: PetrolEngine | DieselEngine;
  tankCapacity?: number;
  electricEngine?: ElectricEngine;
  batteryCapacity?: number;
}
代码语言:javascript
复制
type Vehicle = 
  | GasolineCar
  | ElectricCar

type = GasolineCar {
  kind: "gasolineCar";
  name: string;
  engine: PetrolEngine | DieselEngine;
  tankCapacity: number;
}

type ElectricCar  = {
  kind: "electricCar"
  name: string;
  engine: ElecticEngine;
  batteryCapacity: number;
}

带有受歧视的联合的示例产生了更多的描述性代码。您不必为可选字段添加多个检查--相反,只需通过判别器(尽早)识别类型,并将对象传递给接受更窄类型(GasolineCarElectricCar而不是Vehicle)的函数/方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71306350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档