如何使对象中的所有字段都需要填充或对象中的 none 字段完全被填充?

How to make either all fields in a object required for filling or none of the fields in a object to be filled at all?

我想要的是填写 IT 负责人联系人中的所有字段或填写其中的 none。因此,例如,如果在 IT 负责人联系人对象中填写了名字、姓氏字段,但未填写电子邮件、phone 号码,则会显示错误消息:“您应该填写 IT 负责人联系人中的所有字段或 none 个”。如果 IT 负责人联系人中的所有字段都已填写或未填写,则不会显示任何错误消息。 yup 可以实现吗?我将在图片下方提供代码

这是将发送到后端的对象的最终接口:

interface Contact{
    firstName: string;
    lastName: string;
    email: string;
    phone: string;
}

export interface ICompanyCreation {
    name: string;
    status: Status;
    country: string;
    city: string;
    address: string;
    zipCode: number;
    admin: Contact;
    itHead: Contact;
    customerManager: Contact;
}

这是我的验证模式:

export const validationSchema = yup.object().shape({

    name: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
    country: yup.string().matches(countryRegEx,countryMessage).required(requiredMessage).trim(),
    city: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
    address: yup.string().required(requiredMessage).trim(),
    zipCode: yup.number().positive(positiveNumberMessage).integer(integerNumberMessage).required(requiredMessage).typeError(numberMessage),

    admin: object().shape(
        {
            firstName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            lastName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            phone: yup.string().matches(phoneRegEx, phoneMessage).required(requiredMessage).trim(),
            email: yup.string().email(emailMessage).required(requiredMessage).trim(),
        }
    ),
    itHead: object().shape(
        {
            firstName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            lastName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            phone: yup.string().matches(phoneRegEx, phoneMessage).required(requiredMessage).trim(),
            email: yup.string().email(emailMessage).required(requiredMessage).trim(),
        }
    ),
    customerManager: object().shape(
        {
            firstName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            lastName: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim(),
            phone: yup.string().matches(phoneRegEx, phoneMessage).required(requiredMessage).trim(),
            email: yup.string().email(emailMessage).required(requiredMessage).trim(),
        }
    ),
});

您可以使用如下所示的 itHead 验证架构。这个想法是检查除自身之外的任何字段是否具有某些值。如果是这样,那么字段本身也将被标记为 required。 请注意,传递 普通函数 而不是 箭头函数 给出您可以访问 siblings 属性。另请注意,我已将 nameRegEx 用于所有字段,因此请将其替换为相应的正则表达式。

itHead: Yup.object().shape({
      firstName: Yup.string().test(
        "first-name-test",
        "Please provide last name",
        function (value) {
          const { lastName, phone, email } = this.parent;
          if (lastName || phone || email) {
            return value && nameRegEx.test(value);
          }
          return true;
        }
      ),
      lastName: Yup.string()
        .trim()
        .test("last-name-test", "Please provide last name", function (value) {
          const { firstName, phone, email } = this.parent;
          if (firstName || phone || email) {
            return value && nameRegEx.test(value);
          }
          return true;
        }),
      phone: Yup.string().test(
        "phone-test",
        "Please provide phone",
        function (value) {
          const { firstName, lastName, email } = this.parent;
          if (firstName || lastName || email) {
            return value && nameRegEx.test(value);
          }
          return true;
        }
      ),
      email: Yup.string().test(
        "email-test",
        "Please provide email",
        function (value) {
          const { firstName, phone, lastName } = this.parent;
          if (firstName || phone || lastName) {
            return value && nameRegEx.test(value);
          }
          return true;
        }
      )
    })

实现它的替代方法 when:

itHead: yup.object().shape(
        {
            firstName: yup.string().when(['lastName', 'phone', 'email'], {
                    is: (lastName: string|undefined, phone: string|undefined, email: string|undefined) => {
                        return (!lastName) && (!phone) && (!email);
                    },
                    then: yup.string().notRequired(),
                    otherwise: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim()
                }
            ),
            lastName: yup.string().when(
                ['firstName', 'phone', 'email'],{
                    is: (firstName: string|undefined, phone: string|undefined, email: string|undefined) => {
                        return (!firstName) && (!phone) && (!email);
                    },
                    then: yup.string().notRequired(),
                    otherwise: yup.string().matches(nameRegEx, nameMessage).required(requiredMessage).trim()
                }
            ),
            phone: yup.string().when(
                ['firstName', 'lastName', 'email'],{
                    is: (firstName: string|undefined, lastName: string|undefined, email: string|undefined) => {
                        return (!firstName) && (!lastName) && (!email);
                    },
                    then: yup.string().notRequired(),
                    otherwise: yup.string().matches(phoneRegEx, phoneMessage).required(requiredMessage).trim()
                }
            ),
            email: yup.string().when(
                ['firstName', 'lastName', 'phone'],{
                    is: (firstName: string|undefined, lastName: string|undefined, phone: string|undefined) => {
                        return (!firstName) && (!lastName) && (!phone);
                    },
                    then: yup.string().notRequired(),
                    otherwise: yup.string().email(emailMessage).required(requiredMessage).trim()
                }
            ),
        }, [['firstName', 'lastName'],  ['firstName', 'phone'], ['firstName', 'email'], ['lastName', 'phone'],  ['lastName', 'email'], ['phone', 'email']]
    )