yupでいずれかを必須としたい場合

2023/02/17に公開

A もしくは B いずれか入力してください。的なバリデーションしたい時の話。

const schema = yup
  .object({
    textFieldA: yup
      .string()
      .test('A or B required', 'AかB必須です', (value) => {
        return this.parent.textFieldB || value
      }),
    textFieldB: yup
      .string()
      .test('A or B required', 'AかB必須です', (value) => {
        return this.parent.textFieldA || value
      }),
    ),

さらにnumberが混じっていたりする場合に、空文字はstringなのでnumberとして扱われず、どちらか必須ということができない。

その際は、下記のように、valueの値によって評価する式を分けることで対処できた。

const schema = yup
  .object({
    textFieldA: yup
      .string()
      .test('A or B required', 'AかB必須です', (value) => {
        return this.parent.textFieldB || value
      }),
    textFieldB: yup.lazy((value) => // Bはnumberのフォーム
      value === ''
        ? yup.string()
        : yup
            .number()
            .max(20)
            .test('A or B required', 'AかB必須です', (value) => {
              return this.parent.textFieldA || value
            }),
    ),

参考:

Discussion