如何在 TypeScript 中创建用于条件类型验证的单个 Zod 架构?

问题描述 投票:0回答:1

描述

假设我们有以下一组 TypeScript 接口:

// Indexed type for type-specific fields
interface RichTextMap {
  text?: { text: string };
  equation?: { equation: string };
  mention?: { mention: string };
}

// Main RichText interface with indexed types
interface RichTextBase {
  type: "text" | "mention" | "equation";
  annotations: any;
  plain_text: string;
  href: string | null;
}

type RichText = RichTextBase & (RichTextMap[RichTextBase["type"]] & {});

RichText
类型应允许对象如下:

const text = { 
  type: "text", 
  annotations: {},
  plain_text: "", 
  href: null, 
  text: { text: "" }
}

const mention = { 
  type: "mention", 
  annotations: {},
  plain_text: "", 
  href: null, 
  mention: { mention: "" }
}

问题陈述

我需要为提到的对象定义

zod
模式。

我对

zod
的理解还有待提高,但到目前为止我已经设法提出以下解决方案:

const RichTextSchema = z
  .object({
    type: z.enum(["text", "mention", "equation"]),
    annotations: z.object({}).passthrough(),
    plain_text: z.string(),
    href: z.string().url().nullable(),
});

const TextRichTextSchema = RichTextSchema.extend({
  text: z.object({ text: z.string() }).optional(),
})

const MentionRichTextSchema = RichTextSchema.extend({
  mention: z.object({ mention: z.string() }).optional(),
})

const EquationRichTextSchema = RichTextSchema.extend({
  equation: z.object({ equation: z.string() }).optional(),
})

现在,这种方法的问题是我正在创建三种不同的模式,并且必须弄清楚在运行时调用哪一个。虽然接口类型足够通用,可以在单一类型下容纳不同的对象。

问题:我想知道是否有办法更改

RichTextSchema
,以便能够针对上述接口类型进行验证。本质上,只保留一个模式对象来验证示例中的不同对象。

typescript zod
1个回答
0
投票

您似乎正在寻找的是 Zod 中受歧视工会案例的确切用途。

这是一个基于您的案例的示例:

import { z } from "zod";

const RichTextBaseSchema = z.object({
  annotations: z.object({}).passthrough(),
  plain_text: z.string(),
  href: z.string().url().nullable(),
});

const RichTextSchema = z.discriminatedUnion("type", [

  RichTextBaseSchema.extend({
    type: z.literal("text"),
    text: z.object({ 
      text: z.string() 
    }),
  }),

  RichTextBaseSchema.extend({
    type: z.literal("mention"),
    mention: z.object({ 
      mention: z.string() 
    }),
  }),
  
  RichTextBaseSchema.extend({
    type: z.literal("equation"),
    equation: z.object({ 
      equation: z.string() 
    }),
  }),
]);

type RichText = z.infer<typeof RichTextSchema>;
© www.soinside.com 2019 - 2024. All rights reserved.