typescript - Definere gjensidig rekursive zod-skjemaer


Jeg er ny til TypeScript og jeg får en feil i følgende kode:

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)
});

Feilen er enkel å forstå... fordi variablene er avhengige av hverandre.

ReferenceError: Cannot access 'SpatialPlacement' before initialization

Hvis jeg bytter om på de ovennevnte variablene, altså hvis jeg skriver SpatialPlacement først og deretter SpatialEntity, er feilen fortsatt den samme.

Noen idé om hvordan man kan løse dette?? Enhver ledetråd ville bli satt pris på. Takk!

Svar #1

Problemet på overflaten er at du forsøker å referere til en verdi før dens definisjon. Kjernen i problemet er at dette skjemaet er gjensidig rekursivt, så på et visst nivå vil du trenge z.lazy.

Jeg prøvde å forenkle problemet litt. Et problem med rekursive typer i zod er at du vanligvis må spesifisere typene eksplisitt fordi zod ikke kan slutte seg til hva typene bør være.

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
});

De to tingene dette gjør er:

  1. Det gjør SpatialEntity tilgjengelig for SpatialPlacement ved å definere verdien som en let. Dette lar oss utsette implementeringen av skjemaet for denne enheten, men gjør navnet til en del av omfanget for SpatialPlacement.
  2. Skjemaet SpatialPlacement bruker z.lazy for å utsette løsning av skjemaet for SpatialEntity. Hvis det forsøkte å bruke verdien av SpatialEntity uten z.lazy, ville verdien fortsatt være undefined, og ting ville ikke fungere som forventet. (Prøv å fjerne z.lazy; TypeScript vil klage)

Relaterte artikler