コンパイラかく語りき

import { Fun } from 'programming'

yup のバリデーションで min 指定でも optional にする方法

スキーマバリデーションの yup の話です。

github.com

※この記事執筆時点での yup のバージョンは 1.1.1 となります。

文字列の最小文字数を指定するには、 min を使います。

const schema = yup.object().shape({
  password: yup.string().default('').min(8).optional()
})

この例は「パスワードの入力は必須ではないが、入力するなら8文字以上」という指定のはずでした。

が、フォームを submit しようとすると「未入力」エラーが発生…。optional を指定しているのに…。

調べてみた結果、 when を使って条件文にすると解決できました。

const schema = yup.object().shape({
      password: yup.string().when('password', {
        // もし空文字なら
        is: (password: string) => password === '',
        // 任意項目
        then: (schema) => schema.optional(),
        // 空文字でなければ、8文字以上が必須
        otherwise: (schema) => schema.default('').min(8).required(),
      }),
      [['password', 'password']],
})

ちなみに、この書き方だと cyclic dependency エラーが発生しました。 その対策として、 shape の第二引数として [['password', 'password']] を指定しています。