是的,验证对象数组最多包含一个对象,其中属性 = 值

die*_*uge 6 reactjs yup formik

我正在使用 FormikFieldArray将对象动态添加到数组中,当对象被添加到数组时呈现额外的表单元素push()

我的架构如下所示:

const EMAIL_SCHEMA = Yup.object().shape({
  address: Yup.string().email().required( 'E-mail address is required.' ),
  isPreferredContact: Yup.boolean()
})

const SCHEMA = Yup.object().shape({
  emails: Yup.array()
             .of( EMAIL_SCHEMA )
             .ensure()
             .compact( v => !v.address )
             .required( 'At least one e-mail address is required.' )
})
Run Code Online (Sandbox Code Playgroud)

对于每个电子邮件输入,都有一个相应的复选框来指示它是否是首选的联系电子邮件地址。没有电子邮件地址需要作为首选标记。

我想要做的是验证数组最多包含一个对象,其中isPreferredContactis true。如果在阵列中的3电子邮件对象和isPreferredContactfalse为所有的人,这是一个有效的状态。也就是说:

let values = [
  {address: '1@email.com', isPreferredContact: false},
  {address: '2@email.com', isPreferredContact: false},
  {address: '3@email.com', isPreferredContact: false}
] // OK

let values = [
  {address: '1@email.com', isPreferredContact: true},
  {address: '2@email.com', isPreferredContact: false},
  {address: '3@email.com', isPreferredContact: false}
] // OK

let values = [
  {address: '1@email.com', isPreferredContact: true},
  {address: '2@email.com', isPreferredContact: true},
  {address: '3@email.com', isPreferredContact: false}
] // Invalid
Run Code Online (Sandbox Code Playgroud)

我看到这个答案

是的:对象数组的深度验证

表明该compact()方法可用于验证至少一个,因为如果从数组中删除“假”值后,数组为空,则很容易将架构键视为无效。

但是,我看不到任何东西来验证数组是否最多包含一个具有 property = value 谓词的对象。

有没有办法做到这一点?

die*_*uge 8

在 GitHub 中查看 Yup 的问题后,盯着 API 文档(该文档addMethod非常糟糕),并在 Code Sandbox 中进行测试后,我发现这有效:

Yup.addMethod(Yup.array, 'atMostOne', function(args) {
  const { message, predicate } = args
  return this.test('atMostOne', message, function(list) {
    // If there are 2+ elements after filtering, we know atMostOne must be false.
    return list.filter(predicate).length < 2
  })
})
Run Code Online (Sandbox Code Playgroud)

显然,谓词是一个函数,它接受数组的一个元素并对其执行测试,返回一个boolean

对于标量值数组,这很简单el => el === value。对于对象数组,它将是el => el.property === valueor el[property] === value

希望这可以帮助其他对此感到好奇的人。