zod 有没有相当于 yup 的 oneOf() 的东西

问题描述 投票:0回答:2

如果我有一个属性应该仅限于几个可能的值,使用 Yup 我可以做类似的事情:

prop: Yup.string().oneOf([5, 10, 15])

我似乎在 Zod 中找不到类似的东西。当然,我可以通过以下方式进行验证:

const allowedValues = [5, 10, 15];

const schema = z.object({
  prop: z.number().superRefine((val, ctx) => {
    if (allowedValues.includes(val)) return true;

    ctx.addIssue({
      message: `${ctx.path} must be one of ${allowedValues}`,
      code: "custom",
    });
    return false;
  }),
});

但我想知道是否可以通过编写更少的代码来完成。

typescript validation yup zod
2个回答
8
投票

在这种特殊情况下,您可以将

z.union
z.literal
一起使用,至少可以更加声明性地编写代码:

const schema = z.object({
  prop: z.union([z.literal(5), z.literal(10), z.literal(15)]),
});

此方法还具有将确切类型

5 | 10 | 15
解析为结果而不是简单地
number
的额外好处。

写起来可能会有点乏味,所以如果你发现自己经常这样做来编写一个快速助手,比如:

,这可能是有意义的
// This signature might be a bit overkill but these are the types
// z.literal allows.
function oneOf<T extends string | number | boolean | bigint | null | undefined>(
  t: readonly [T, T, ...T[]],
) {
  // A union must have at least 2 elements so to work with the types it
  // must be instantiated in this way.
  return z.union([
    z.literal(t[0]),
    z.literal(t[1]),
    // No pointfree here because `z.literal` takes an optional second parameter
    ...t.slice(2).map(v => z.literal(v)),
  ])
}

// This will be equivalent to the first schema
const schema2 = z.object({
  // This will still typecheck without as const but with weaker
  // types than the first example.
  prop: oneOf([5,10,15] as const),
});

0
投票

如果您正在处理的类型是字符串文字集,则可以在较新版本的 Zod 中使用速记运算符:

type Levels = "One" | "Two" | "Three"

const LevelsSchema = z.enum(["One", "Two", "Three"])

© www.soinside.com 2019 - 2024. All rights reserved.