发布于 2026-01-06 1 阅读
0

如何使用 Yup 验证两个相互依赖的字段

如何使用 Yup 验证两个相互依赖的字段

大家好,我们直奔主题,我将向你们展示如何使用 Yup 验证两个相互依赖的字段。

你可能已经遇到过这个问题了。如果没有,你迟早会遇到。

以下是一个例子:

const yup = require('yup')
const {
  setLocale
} = yup

setLocale({
  mixed: {
    notType: 'the ${path} is obligatory',
    required: 'the field ${path} is obligatory',
    oneOf: 'the field ${path} must have one of the following values: ${values}'
  }
})

const myNameSchema = yup.object().shape({
  first_name: yup.string().ensure().when('surname', {
    is: '',
    then: yup.string().required()
  }),
  surname: yup.string().ensure().when('first_name', {
    is: '',
    then: yup.string().required()
  })
})

[...]

Error: Cyclic dependency, node was:"surname"
at visit (/home/{yourPath}/node_modules/toposort/index.js:45:13)
at visit (/home/{yourPath}/node_modules/toposort/index.js:62:9)
at visit (/home/{yourPath}/node_modules/toposort/index.js:62:9)
at Function.toposort [as array]...


这是循环错误,我们该如何解决这个问题?

相互依赖才能进行验证的字段需要排序,以便按正确的顺序“构造”它们,例如,如果依赖于A字段中的字段B,则需要在将字段中的值传递给之前对其进行转换和强制转换。A B

这里发生的情况是,我们只是在条件中添加了一个验证,所以实际上没有必要在所有内容都构建完成后再请求进行验证。由于Yup的灵活性和程序化特性,它无法区分这两种情况。


解决方案:

const yup = require('yup')
const {
  setLocale
} = yup

setLocale({
  mixed: {
    notType: 'the ${path} is obligatory',
    required: 'the field ${path} is obligatory',
    oneOf: 'the field ${path} must have one of the following values: ${values}'
  }
})

const myNameSchema = yup.object().shape({
  first_name: yup.string().ensure().when('surname', {
    is: '',
    then: yup.string().required()
  }),
  surname: yup.string().ensure().when('first_name', {
    is: '',
    then: yup.string().required()
  })
}, [['surname', 'first_name']]) // <--- adding your fields which need validation

[...]
{
    "message": "there was an error validating data",
    "error": [
        "the field first_name is obligatory",
        "the field surname is obligatory"
    ]
}

另一个包含额外字段的示例:

[...]
const myNameSchema = yup.object().shape({
  first_name: yup.string().when(['surname', 'age'], {
    is: (surname, age) => !surname && !age,
    then: yup.string().required()
  }),
  surname: yup.string().when(['first_name', 'age'], {
    is: (first_name, age) => !first_name && !age,
    then: yup.string().required()
  }),
  age: yup.number().when(['first_name', 'surname'], {
    is: (first_name, surname) => !first_name && !surname,
    then: yup.number().required()
  })
}, [
  ['first_name', 'surname'], // <--- adding your fields which need validation
  ['first_name', 'age'],
  ['surname', 'age']
])

[...]
{
    "message": "there was an error validating data",
    "error": [
        "the field first_name is obligatory",
        "the field surname is obligatory",
        "the field age is obligatory"
    ]
}

希望对你有帮助!😉
谢谢!!


我的GitHub 😎

文章来源:https://dev.to/gabrieltrriaga/how-to-validate-two-fields-that-depend-on-each-other-with-yup-1ccg