有没有办法让对象数组包含一些文字?
Is there a way to have an array of objects with some of them literals?
我正在考虑使用 zod 进行以下验证,但我不知道如何进行(或者是否可以使用 zod)。
我想要一个对象数组,所有对象都具有相同的形状,其中一些具有文字道具,我需要它们始终存在于数组中。
示例:
我总是需要在数组中包含名称为 required1 和 required2 的对象,然后是具有相同形状的其他对象选项。
[
{
name: z.literal('required1'),
otherprop: z.number()
},
{
name: z.literal('required2'),
otherprop: z.number()
},
// I want to include one or more of the following too (optionals).
{
name: z.string(),
otherprop: z.number()
},
]
另一个示例需要抛出,因为缺少 required2
[
{
name: z.literal('required1'),
otherprop: z.number()
},
// I want to include one or more of the following too.
{
name: z.string(),
otherprop: z.number()
},
]
有线索吗?
仅靠打字系统无法解决问题。我使用 Zod 的 refine
方法解决了这个问题。我将 post 两个版本,一个更简单 refine
,另一个更复杂 superRefine
。
基本代码
const elementSchema = z.object({
name: z.string(),
otherprop: z.number(),
})
type Element = z.infer<typeof elementSchema>;
// In my real code, here I have a function that returns the array of required names for the case.
const names = ['required1', 'required2'];
function refineNames(elements: Element[]): boolean {
return names.every((el: string) => elements.some(x => x.name === el));
}
使用精炼的简单方法
z.array(elementSchema).refine(
(elements) => refineNames(elements),
{ message: `There are missing names. Required names are ${names.join(', ')}`, }
);
使用 superRefine 的复杂方法。但是我们也可以比较重复的条目。
function hasDuplicates(elements: Element[]): boolean {
const names = elements.map(e => e.name);
return names.length !== new Set(names).size;
}
z.array(elementSchema).superRefine((elements, ctx) => {
if (refineNames(elements)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `There are missing names. Required names are ${names.join(', ')}`,
});
}
if (hasDuplicates(elements)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'No duplicated name allowed.',
});
}
}),
参考文献:
我正在考虑使用 zod 进行以下验证,但我不知道如何进行(或者是否可以使用 zod)。 我想要一个对象数组,所有对象都具有相同的形状,其中一些具有文字道具,我需要它们始终存在于数组中。
示例: 我总是需要在数组中包含名称为 required1 和 required2 的对象,然后是具有相同形状的其他对象选项。
[
{
name: z.literal('required1'),
otherprop: z.number()
},
{
name: z.literal('required2'),
otherprop: z.number()
},
// I want to include one or more of the following too (optionals).
{
name: z.string(),
otherprop: z.number()
},
]
另一个示例需要抛出,因为缺少 required2
[
{
name: z.literal('required1'),
otherprop: z.number()
},
// I want to include one or more of the following too.
{
name: z.string(),
otherprop: z.number()
},
]
有线索吗?
仅靠打字系统无法解决问题。我使用 Zod 的 refine
方法解决了这个问题。我将 post 两个版本,一个更简单 refine
,另一个更复杂 superRefine
。
基本代码
const elementSchema = z.object({
name: z.string(),
otherprop: z.number(),
})
type Element = z.infer<typeof elementSchema>;
// In my real code, here I have a function that returns the array of required names for the case.
const names = ['required1', 'required2'];
function refineNames(elements: Element[]): boolean {
return names.every((el: string) => elements.some(x => x.name === el));
}
使用精炼的简单方法
z.array(elementSchema).refine(
(elements) => refineNames(elements),
{ message: `There are missing names. Required names are ${names.join(', ')}`, }
);
使用 superRefine 的复杂方法。但是我们也可以比较重复的条目。
function hasDuplicates(elements: Element[]): boolean {
const names = elements.map(e => e.name);
return names.length !== new Set(names).size;
}
z.array(elementSchema).superRefine((elements, ctx) => {
if (refineNames(elements)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `There are missing names. Required names are ${names.join(', ')}`,
});
}
if (hasDuplicates(elements)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'No duplicated name allowed.',
});
}
}),
参考文献: