我正在尝试为Zod创建一个可以从以下数据派生的多级模式:
{
"data": [
{
"title": "Devices",
"items": [
{
"items": [
{
"title": "something",
"url": "/products/devices/something"
},
{
"title": "something3",
"url": "/products/devices/something3"
},
{
"title": "something2",
"url": "/products/devices/something2"
}
],
"title": "Flower + Concentrates",
"url": "/devices/flower-and-concentrate"
},
{
"items": [
{
"title": "something",
"url": "/products/devices/something"
},
{
"title": "something3",
"url": "/products/devices/something3"
},
{
"title": "something2",
"url": "/products/devices/something2"
}
],
"title": "something",
"url": "/devices/something"
}
]
},
{
"title": "CBD",
"items": [
{
"title": "something",
"url": "/products/devices/something"
},
{
"title": "something3",
"url": "/products/devices/something3"
},
{
"title": "something2",
"url": "/products/devices/something2"
}
]
}
...
到目前为止我有:
export const menuItemSchema = z.object({
url: z.string(),
title: z.string(),
});
export const menuSchema = z.object({
url: z.string().optional(),
title: z.string(),
items: z.array(menuItemSchema),
});
然而,我不知道如何使menuSchema
递归以考虑多级菜单。我已经阅读了文档,但没有看到任何关于这方面的内容。对于上下文,我使用CMS来获取此数据,并使用Zod来确保所有菜单都遵守此模式。因此,它也应该能够在一级菜单上工作。
编辑:
我找到了一个递归的文档,但是看起来我可能在某个地方搞砸了,因为你可以在我只需要title, items, and url
的地方传入额外的键:
const baseMenu = z.object({
title: z.string().optional(),
url: z.string().optional(),
});
type Menu = z.infer<typeof baseMenu> & {
items?: Menu[];
};
const MenuSchema: z.ZodType<Menu> = baseMenu.extend({
items: z.lazy(() => MenuSchema.array().optional()),
});
console.log(MenuSchema.safeParse({
data: [
{
title: 'Devices',
items: [
{
items: [
{
title: 'something',
url: '/products/devices/something',
},
{
title: 'something3',
url: '/products/devices/something3',
},
{
title: 'something2',
url: '/products/devices/something2',
},
],
title: 'Flower + Concentrates',
url: '/devices/flower-and-concentrate',
},
{
items: [
{
title: 'something',
url: '/products/devices/something',
},
{
title: 'something3',
url: '/products/devices/something3',
},
{
title: 'something2',
url: '/products/devices/something2',
},
],
title: 'something',
url: '/devices/something',
},
],
},
{
title: 'CBD',
items: [
{
title: 'something',
url: '/products/devices/something',
},
{
title: 'something3',
url: '/products/devices/something3',
},
{
title: 'something2',
url: '/products/devices/something2',
},
],
},
],
}))
1条答案
按热度按时间n6lpvg4x1#
通过查看数据,我确定了两种不同的类型。一种是没有URL的顶级菜单项类型,另一种是具有
url
、title
以及可选的菜单项递归列表的菜单项。我认为您陷入困境的地方在于顶级菜单项类型与菜单项非常相似。但我认为最好将它们视为两种不同的类型。记住这一点,您可以将您的模式表述如下:然后,您可以使用类似下面的语句来解析输入数据