You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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()自定义类型,直接验证实例类型而非结构,同时支持设置默认值:

  1. 定义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实例"
  }
);
  1. 创建带默认值的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>;
  1. 测试验证
// 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:01:02