typescript 如何使用zod字段根据条件有不同的验证

egdjgwm8  于 2023-05-23  发布在  TypeScript
关注(0)|答案(1)|浏览(146)

我们正在做一个项目,我们在前端和后端之间共享类型。部分字段为mongodb.bson.ObjectId类型。有没有一种方法可以在同一类型的文件中有选择地进行验证,这样在后端就像ObjectId一样处理,而在前端就像String一样处理。类型的代码如下:

import { z } from "zod";
import { ObjectId } from "bson";

export const AITypeObjectIdTransform = z.custom<ObjectId>().transform(value => new ObjectId(value));
export type AITypeObjectIdTransform = z.infer<typeof AITypeObjectIdTransform>;

export const BaseObject = z.object({
  _id: AITypeObjectIdTransform.optional(),
});

我们希望_id在后端被视为AITypeObjectIdTransform.optional(),在前端被视为zod.string().optional()。

ycggw6v2

ycggw6v21#

可以使用.merge方法,
如果两个架构共享键,则B的属性将覆盖A的属性。返回的模式还继承了“unknownKeys”策略(strip/strict/passthrough)和B的catchall模式。

export const BaseObject = z.object({
  _id: AITypeObjectIdTransform.optional(),
});

export const BaseObjectFrontend = BaseObject.merge(z.object({
  _id: z.string().optional(),
}));

从屏幕截图中可以看到,类型是正确的。如果您有其他属性,它们将保持原样,而不需要复制它们。

TypeScript Playground:https://tsplay.dev/w6GzRN
如果出于某种原因,您需要同一个变量来拥有这两种类型,那么您将需要一个环境变量或类似变量来控制其值,例如

export const BaseObject = z.object({
  _id: (process.env.FRONTEND ? z.string() : AITypeObjectIdTransform).optional(),
});

但这会打乱你的TypeScript类型。

相关问题