如何在使用 Yup 不允许类型强制的同时允许字段未定义?

How do I allow a field to be undefined while disallowing type coercion using Yup?

我正在尝试使用 yup 验证对象的字段。

这些是我的要求:

  1. 该字段应为字符串或未定义。
  2. 如果未定义,应该给它一个默认值。
  3. 如果它是其他类型的值,则不应将其强制转换为字符串。相反,它应该是不兼容的并且会导致错误。

到目前为止我已经尝试了以下方法:

一个。以下模式不会阻止类型强制。例如当值为数字时,它通过验证。但是,我希望它无法通过验证。

const schema = yup.object().shape({
  myField: yup.string().default('myDefaultString')
});

乙。以下架构可防止类型强制转换,但当我传递未定义的值时它会失败。如果给出未定义的值,我实际上希望该值为 'myDefaultString'。

const schema = yup.object().shape({
  myField: yup.string().strict(true).default('myDefaultString')
});

C。以下架构与选项 B 具有相同的结果。

const schema = yup.object().shape({
  myField: yup.string().strict(true).notRequired().default('myDefaultString')
});

D.在使用 validateSync 方法验证架构时,使用 strict: true 作为选项的一部分。同样,这与 B.

具有相同的结果

非常感谢对此的任何帮助,谢谢!

我认为您可以按如下方式扩展 yup 字符串:

class StrictString extends yup.string {
  constructor() {
    super();
    transforms = []; // remove the default type coercion transforms
  }
}

然后,将 StrictString() 替换为 yup.string()。 这将符合要求。

Yup 能够使用 yup.lazy* 满足您的所有三个要求,它在 validation/cast 时间创建一个模式。它的可读性也很高,因为它使用了易于理解的 switch 语句。

下面根据你的条件评估一个值:

const StringOrUndefinedSchema = yup.lazy((value) => {
  switch (typeof value) {
    case 'undefined':
      return yup.string().default('myDefaultString');
    case 'string':
      return yup.string().strict();
    default:
      throw new yup.ValidationError("Value must be a string or `undefined`"); 
  }
});

然后它可以在任何地方使用,包括您示例中的对象字段:

const ObjectWithFieldSchema = yup.object({
  myField: StringOrUndefinedSchema,
});

综合起来:

const yup = require("yup");

const StringOrUndefinedSchema = yup.lazy((value) => {
  switch (typeof value) {
    case 'undefined':
      return yup.string().default('myDefaultString');
    case 'string':
      return yup.string();
    default:
      throw new yup.ValidationError("Value must be a string or `undefined`"); 
  }
});

const ObjectWithFieldSchema = yup.object({
  myField: StringOrUndefinedSchema,
});

const iWillDefault = await ObjectWithFieldSchema.validate({ });
const iWillBeStrict = await ObjectWithFieldSchema.validate({ myField: "I am a string" });

console.log(iWillDefault); // { myField: "myDefaultString" }
console.log(iWillBeStrict); // { myField: "I am a string" }

在此处查看之前关于 RunKit 的示例代码:https://runkit.com/joematune/6138658a9113f00008292564