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

如何解决TypeScript中Zod循环引用Schema导致的TS7022错误?

解决Zod循环依赖Schema的TS7022错误

核心方案:给顶层联合Schema添加显式类型注解

直接给screenSchema声明类型,再完成赋值,就能让TypeScript正确解析循环引用的类型:

import { z } from "zod";

// 先声明screenSchema的类型,关联drawerScreenSchema的类型
export let screenSchema: z.ZodDiscriminatedUnion<"screenType", [typeof drawerScreenSchema]>;

export const drawerScreenSchema = z.object({
  screenType: z.literal("Drawer"),
  name: z.string(),
  initialScreen: z.string().optional(),
  screens: z.array(z.lazy(() => screenSchema)).optional(),
});

// 赋值screenSchema,后续可直接添加其他子Schema
screenSchema = z.discriminatedUnion("screenType", [
  drawerScreenSchema,
  // 示例:添加其他类型的Screen Schema
  // z.object({ screenType: z.literal("Modal"), name: z.string(), content: z.string() })
]);

多子Schema场景的扩展方案

如果需要支持更多类型的Screen Schema,可以先声明所有子Schema的类型占位,再统一定义顶层联合Schema:

import { z } from "zod";

// 声明子Schema的类型,明确循环引用关系
export let drawerScreenSchema: z.ZodObject<{
  screenType: z.ZodLiteral<"Drawer">;
  name: z.ZodString;
  initialScreen: z.ZodOptional<z.ZodString>;
  screens: z.ZodOptional<z.ZodArray<typeof screenSchema>>;
}>;

export let tabScreenSchema: z.ZodObject<{
  screenType: z.ZodLiteral<"Tab">;
  name: z.ZodString;
  tabs: z.ZodArray<typeof screenSchema>;
}>;

// 声明顶层联合Schema的类型
export let screenSchema: z.ZodDiscriminatedUnion<"screenType", [typeof drawerScreenSchema, typeof tabScreenSchema]>;

// 定义子Schema的具体结构
drawerScreenSchema = z.object({
  screenType: z.literal("Drawer"),
  name: z.string(),
  initialScreen: z.string().optional(),
  screens: z.array(z.lazy(() => screenSchema)).optional(),
});

tabScreenSchema = z.object({
  screenType: z.literal("Tab"),
  name: z.string(),
  tabs: z.array(z.lazy(() => screenSchema)),
});

// 组装联合Schema
screenSchema = z.discriminatedUnion("screenType", [
  drawerScreenSchema,
  tabScreenSchema,
]);

错误原因说明

TS7022错误的本质是:TypeScript无法自动推断存在循环引用变量的类型,因为在初始化screenSchema时,它被drawerScreenSchema间接引用,导致类型推断陷入循环。通过显式添加类型注解,我们给TypeScript提供了明确的类型信息,绕过了自动推断的限制。

而Zod本身提供的z.lazy()已经处理了运行时的循环引用问题,只需配合类型注解解决编译时的TS错误即可。

内容的提问来源于stack exchange,提问作者DxW

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:40:33