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

如何正确使用Zod递归类型并进行类型推断?

解决Zod循环引用导致的TypeScript类型推断错误

你的问题是因为barSchema和fooSchema互相循环引用,TypeScript在初始化时无法自动推断它们的类型,所以抛出了隐式any的错误。以下两种方法可以解决问题,同时完全保留类型推断能力:

方法一:使用z.lazy()延迟引用Schema

这是最直接的解决方案,通过z.lazy()延迟获取对方的Schema,避免初始化阶段的循环引用,让TypeScript能正确推断类型:

import { z } from "zod";

// 先定义其中一个Schema,用z.lazy引用未定义的对象
export const fooSchema = z.object({
  id: z.string(),
  bar: z.lazy(() => barSchema),
});

// 再定义另一个Schema,同样用z.lazy
export const barSchema = z.object({
  id: z.string(),
  foo: z.lazy(() => fooSchema),
});

// 正常进行类型推断
export type BarType = z.infer<typeof barSchema>;
export type FooType = z.infer<typeof fooSchema>;

z.lazy()的作用是返回一个延迟解析的Zod类型,只有在实际验证或类型推断时才会去获取引用的Schema,这样就打破了初始化时的循环依赖,TypeScript能正常跟踪每个Schema的结构,自动生成对应的类型。

方法二:提前声明类型并指定Schema类型(可选)

如果你需要更明确的类型前置声明,也可以先定义类型,再给Schema指定类型参数,同样结合z.lazy()使用:

import { z } from "zod";

// 前置声明类型,基于后续的Schema推断
export type FooType = z.infer<typeof fooSchema>;
export type BarType = z.infer<typeof barSchema>;

// 给Schema指定明确的类型,同时用z.lazy延迟引用
export const fooSchema: z.ZodType<FooType> = z.object({
  id: z.string(),
  bar: z.lazy(() => barSchema),
});

export const barSchema: z.ZodType<BarType> = z.object({
  id: z.string(),
  foo: z.lazy(() => fooSchema),
});

这种方法和第一种效果一致,只是多了一层类型的前置声明,适合需要提前暴露类型的场景。

为什么原写法报错?

你之前的代码直接在z.object()里引用了未初始化的Schema,TypeScript在解析变量初始化时,无法确定未定义变量的类型,只能默认标记为any,而z.lazy()通过延迟求值的方式,让TS在类型检查阶段能正确获取到对方的Schema结构,从而完成类型推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:55:01