typescript 定义相互递归的zod模式

f87krz0w  于 2023-04-22  发布在  TypeScript
关注(0)|答案(1)|浏览(128)

我是TypeScript的新手,在下面的代码中出现了一个错误:

import { z } from "zod";

export const SpatialEntity = z.object({
  dimension_units: z.string().optional(),
  placement: SpatialPlacement
});

export const SpatialPlacement = SpatialPlacementCommon.extend({
  source: z.string().or(SpatialEntity).optional(),
  target: z.string().or(SpatialEntity)
});

误差是直接的...因为变量是相互依赖的。

ReferenceError: Cannot access 'SpatialPlacement' before initialization

如果我交换上述变量,即如果我先写SpatialPlacement,然后写SpatialEntity,那么错误也是一样的。
任何想法如何解决这个问题??任何线索将不胜感激。谢谢!

2guxujil

2guxujil1#

问题是你试图在定义之前引用一个值,问题的核心是这个模式是相互递归的,所以在某种程度上你需要z.lazy
zod中递归类型的一个问题是,你通常需要显式地指定类型,因为zod不能推断出应该是什么类型。

import { z } from "zod";

interface ISpacialEntity {
  dimension_units?: string;
  placement: ISpacialPlacement;
}

interface ISpacialPlacement {
  source?: string | ISpacialEntity;
  target: string | ISpacialEntity;
}
let SpatialEntity: z.ZodType<ISpacialEntity>;
export const SpatialPlacement: z.ZodType<ISpacialPlacement> = z.object({
  source: z.lazy(() => z.string().or(SpatialEntity).optional()),
  target: z.lazy(() => z.string().or(SpatialEntity))
});

SpatialEntity = z.object({
  dimension_units: z.string().optional(),
  placement: SpatialPlacement
});

它做的两件事是:
1.它通过将值定义为let,使SpatialEntitySpatialPlacement可用。这允许我们推迟实现该实体的模式,但使名称成为SpatialPlacement作用域的一部分。

  1. SpatialPlacement架构使用z.lazy来推迟解析SpatialEntity的架构。如果它试图使用不带z.lazySpatialEntity的值,则值仍为undefined,并且无法按预期工作。(尝试删除z.lazy;typescript将抱怨)

相关问题