我正在尝试使用 Zod 在使用 Firebase Firestore 时获得某种类型的理智(这是 Firestore 特有的)。假设我有这样的类型:
export type FooType = {
id: string;
relatedDocument: DocumentReference;
otherRelatedDocument: DocumentReference;
};
我想用 Zod 模式验证它,就像这样:
export const fooTypeSchema = z.object({
id: z.string(),
relatedDocument: ???,
otherRelatedDocument: ???,
});
如果我想做的只是验证,看起来我可以用这样的结构来完成它:
const dataConverterSchema = z.object({
fromFirestore: z.function(),
toFirestore: z.function(),
});
const docRefDocDataSchema =
z.object({
constructor: z.function(),
converter: z.union([dataConverterSchema, z.null()]),
firestore: z.object({ constructor }),
id: z.string(),
parent: z.object({ constructor }),
path: z.string(),
type: z.literal('document'),
withConverter: z.function(),
});
...但现在说我想做这样的事情:
export const fooTypeSchema = z.object({
id: z.string(),
relatedDocument: docRefDocDataSchema.default(() => doc(TABLE_NAME, DOC_ID)),
otherRelatedDocument: docRefDocDataSchema.default(() => doc(TABLE_NAME, DOC_ID)),
});
这是行不通的。我怀疑有很多事情在起作用,但链中的第一个错误消息是关于
DocumentReference<DocumentData>
的构造函数如何是私有的(事实上,doc()
是它的工厂函数)。
这里的最终目标是能够执行以下操作:
const newObj = fooTypeSchema.parse({id: "Foo"});
并获取一个有效的对象,其中填充了默认创建的 docRefs。我见过许多基于 Zod 的库声称可以处理 docRefs(Fireschema 和 Firesword),它们声称支持 docRefs,但它们似乎不处理默认值,只处理验证。
总体而言,Zod 似乎非常擅长处理原始类型,但是当我引入类(更不用说具有私有构造函数等花哨东西的类)时,它似乎变得很困难。
有办法做到这一点吗?
z.instanceof
来解析文档引用,但这会遇到与您的架构相同的“私有构造函数”问题。
refine
的类型保护来解决这个问题,例如:
const docRefDocDataSchema = z.object({}).refine(
(x: object): x is DocumentReference => x instanceof DocumentReference,
);
您可以按原样在原始架构中使用它。
为什么不像下面这样呢?
z.custom<DocumentReference>(
(val) => {
return val instanceof DocumentReference;
},
);