zod icon indicating copy to clipboard operation
zod copied to clipboard

Recursive schema

Open la-ruee-vers-le-bois opened this issue 1 year ago • 2 comments

Hello,

I'm currently experiencing a problem that I can't solve.

I have a recursion problem between two schemas and I don't understand how to do it.

My first schema OrderResponseSchema:

export const OrderSchema = z.object({
  [...]
  account: CustomerSchema,
  [...]
});

export type OrderResponse = z.infer<typeof OrderResponseSchema>

export const OrderResponseSchema = z.object({
  count: z.number(),
  page_count: z.number(),
  page: z.number(),
  results: z.array(OrderSchema)
})

And my second CustomerSchema which extends the OrderResponseSchema in the orders object:

import { OrderResponseSchema } from "./Order";
import { z } from 'zod';

export type Customer = z.infer<typeof CustomerSchema>

export const CustomerSchema = z.object({
  [...]
  orders: z.optional(OrderResponseSchema),
});

This is the error I'm encountering:

'CustomerSchema' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.ts(7022)
const CustomerSchema: any

This error disappears if I comment out the orders object.

Thanks for your help

Versions:

"typescript": "5.1.3",
"zod": "^3.22.4"

la-ruee-vers-le-bois avatar Mar 16 '24 20:03 la-ruee-vers-le-bois

So what I guess is happening is an infinite loop where you try to get 1 schema for customer that has orders and 1 schema for orders that have accounts. However, they are linked so it will just keep linking.

Instead make schemas without the linked properties (eg: CustomerSchema without orders) and use that as schema for your order accounts, same for the OrderSchema in orders, remove the linked items.

If you want to use these linked properties, I suggest to do something like this:

typscriptlang.org/play#code/...

You will see the exact error you get once you change the Order to OrderWithAccount and Customer to CustomerWithOrder.

m10rten avatar Mar 17 '24 12:03 m10rten

There are docs here on how to properly define recursive types: https://github.com/colinhacks/zod?tab=readme-ov-file#recursive-types

I'm afraid this is a little onerous at the moment and does require an explicit type annotation. This will hopefully not be necessary in Zod 4.

colinhacks avatar Mar 19 '24 23:03 colinhacks