🧩

[React-Hook-Form] yupのtips [yup]

2023/04/21に公開

yupを使う機会があったのでメモ

schemaから型を生成する

const schema = yup.object({
  name: yup.string().required(),
  gender: yup
    .string()
    .required()
    .oneOf(['male', 'female', 'other'] as const),
})
interface User extends yup.InferType<typeof schema> {}
// または
type User = yup.InferType<typeof schema>

{
    name: string;
    gender: string;
}

入力した値によってバリデーションを変えたいとき

例 : 性別が男性の場合のみ住所の入力を必須にする

  • when()を使う
const schema = yup.object({
  name: yup.string().required(),
  gender: yup.string().required().oneOf(['male', 'female', 'other']),
  address: yup.string().when('gender', {
    is: 'male',
    then: yup.string().required(),
  }),
})
  • test()を使う
const schema = yup.object({
  name: yup.string().required(),
  gender: yup.string().required().oneOf(['male', 'female', 'other']),
  address: yup
    .string()
    .test('NO_ADDRESS', '住所を入力してください', function (value) {
      if (this.parent.gender !== 'male') {
        //男性以外は住所入力は任意なのでテストをパスする
        return true
      }
      //入力があればテストパス、入力がない場合は場合はエラー表示
      return !!value
    }),
})

schemaに引数を渡して動的に作成したいとき

  • 関数にして引数を受け取り、schemaを返す

例) ペットを飼っている人のみ住所の入力を必須にする

const createSchema = (pets?: { name: string }[]) => {
  return yup.object({
    name: yup.string().required(),
    address: yup
      .string()
      .test('NO_ADDRESS', '住所を入力してください', function (value) {
        //ペットを飼っていない人はテストをパス
        if (!pets) {
          return true
        }
        //入力があればテストパス、ない場合はエラーをを表示
        return !!value
      }),
  })
}

配列の型を指定する

statuses1 → バリデーションは機能するがnumber[]
statuses2 → バリデーションを機能させつつStatus[]

statusは適当です

//0: 下書き 1: 作成済 2: エラー
type Status = 0 | 1 | 2
const statuses: Status[] = [0, 1, 2]

const sampleSchema = object({
  statuses1: array().of(number().required().oneOf(statuses)).required(),
  statuses2: array().of(mixed<Status>().oneOf(statuses).required()).required(),
})
type SampleFormData = InferType<typeof sampleSchema>
type SampleFormData = {
statuses1: number[];
statuses2: (Status)[];
}

参考

Discussion