我使用的是佐德,并且有一个数组,其中包含使用友联市的不同对象。解析完后,我想迭代每一项并提取它为“真实”类型/切断其他类型。
在检查特定对象属性时,以下代码工作正常:
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');
}
});另一种选择是使用受歧视的工会来实现
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');
}
});但是我想我误解了这个概念,因为需要编写更多的代码(我总是可以添加一个共享属性并检查这个属性)。对此的任何帮助都是非常感谢的:)
是否有更好的方法来识别特定的模式?
发布于 2022-03-09 17:37:18
如果我对您的理解是正确的,那么您的问题归结为“为什么要使用受歧视的联合,而不是将共享字段与可选字段结合起来”。(zod.js只是将这个概念提升到运行时,提供验证功能)。在您的示例中,实际上没有理由使用判别器(type属性),因为每个对象只有一个非可选属性,该属性在类型之间相互排斥,可以很容易地用于区分类型。但是,这个代码的主要问题是对象名称(或形状/结构)不传递任何意图--这就是为什么很难看到受歧视的联合的好处。
您可以将区分联合看作是描述的一种类型,它是一个对象族,并提供了一个统一的机制(以鉴别器属性的形式)来标识它们。这种方法比检查是否存在一些手动选择的属性(例如num属性)更不脆弱。如果num由于任何原因成为可选的,怎么办?那你的存亡支票就会破了。受歧视联合的另一个论点是减少可选属性的数量。比较以下两个例子:
// shared and optional fields instead of discriminated union
type Vehicle = {
name: string;
combustionEngine?: PetrolEngine | DieselEngine;
tankCapacity?: number;
electricEngine?: ElectricEngine;
batteryCapacity?: number;
}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;
}带有受歧视的联合的示例产生了更多的描述性代码。您不必为可选字段添加多个检查--相反,只需通过判别器(尽早)识别类型,并将对象传递给接受更窄类型(GasolineCar或ElectricCar而不是Vehicle)的函数/方法。
https://stackoverflow.com/questions/71306350
复制相似问题