如何用Zod验证含Firestore DocumentReference的Schema并设置默认值?
在Firebase Firestore中用Zod实现带默认值的DocumentReference类型安全验证
我在使用Firebase Firestore时,希望借助Zod保障类型安全性,针对Firestore场景定义了如下类型:
export type FooType = { id: string; relatedDocument: DocumentReference; otherRelatedDocument: DocumentReference; };
我想用Zod为其创建验证Schema,但设置默认值时遇到了问题。之前通过结构匹配的方式只能实现基础验证:
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"});时,能自动填充默认生成的合法DocumentReference对象。试过Fireschema、Firesword这类基于Zod的库,它们只能做验证,处理不了默认值。
可行解决方案
核心思路是用Zod的z.custom()自定义类型,直接验证实例类型而非结构,同时支持设置默认值:
- 定义DocumentReference的Zod自定义类型
import { z } from "zod"; import { doc, DocumentReference } from "firebase/firestore"; // 自定义验证DocumentReference实例的Schema const documentReferenceSchema = z.custom<DocumentReference>( (value) => value instanceof DocumentReference, { message: "必须是Firestore DocumentReference实例" } );
- 创建带默认值的FooType Schema
// 替换成你实际的集合名和文档ID常量 const TABLE_NAME = "your-collection"; const DOC_ID = "default-doc-id"; export const fooTypeSchema = z.object({ id: z.string(), relatedDocument: documentReferenceSchema.default(() => doc(TABLE_NAME, DOC_ID)), otherRelatedDocument: documentReferenceSchema.default(() => doc(TABLE_NAME, DOC_ID)), }); // 自动推导类型,和原FooType完全一致 export type FooType = z.infer<typeof fooTypeSchema>;
- 测试验证
// 调用parse时自动填充默认的DocumentReference const newObj = fooTypeSchema.parse({ id: "Foo" }); console.log(newObj.relatedDocument instanceof DocumentReference); // true
扩展:验证特定集合的DocumentReference
如果需要限制DocumentReference必须属于某个特定集合,可以扩展验证逻辑:
const specificCollectionDocRefSchema = z.custom<DocumentReference>( (value) => value instanceof DocumentReference && value.parent?.path === `/${TABLE_NAME}`, // 验证父集合路径 { message: `必须是${TABLE_NAME}集合下的DocumentReference` } );
内容的提问来源于stack exchange,提问作者ipmcc
相关产品推荐
相关产品推荐

