はじめに
フォームのバリデーションを自前で書き始めると、あっという間にif文だらけになります。「名前は必須で1文字以上」「メールアドレスの形式チェック」「パスワードは8文字以上かつ確認用と一致」――条件が増えるたびにコードが読みにくくなり、どこかで判定漏れが起きる。そんな経験がある方は多いのではないでしょうか。
Yupは、こうしたバリデーションのルールをスキーマという形で宣言的に書けるライブラリです。オブジェクトの形状と制約をチェーンメソッドで定義し、validate() や cast() に値を渡すだけで検証・型変換ができます。Formikの検証ライブラリとして長く使われてきた実績があり、React Hook FormやFormikと組み合わせるのが定番の使い方です。
とはいえ、読むより触った方が早いと思います。ブラウザ上でYupのスキーマ定義とバリデーション結果をその場で確認できるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
Yupとは
Yup(GitHub: jquense/yup)は、「Dead simple Object schema validation」を掲げるオブジェクトスキーマ検証ライブラリです。JavaScriptオブジェクトの構造と値の制約をスキーマとして定義し、実行時に値を検証・変換します。2026年時点でのnpm最新版は1.7.1で、開発は活発に続いています。
主な特徴
- チェーン可能なスキーマAPI -
yup.object({ name: yup.string().required() })のように、読みやすいメソッドチェーンでバリデーションルールを組み立てられる - TypeScriptとの親和性 -
InferType<typeof schema>でスキーマから静的型を導出でき、スキーマと型定義の二重管理を避けられる - 値のキャスト(変換)機能 - 文字列で受け取った数値や日付を、検証と同時に適切な型へ変換できる
- 非同期バリデーション対応 -
test()に非同期関数を渡せるため、サーバーサイド・クライアントサイド双方のカスタムルールに対応できる - Formikとの相性の良さ -
validationSchemaプロパティにYupのスキーマをそのまま渡せる作りになっており、Reactのフォームライブラリと組み合わせて使われることが多い
インストール
npmまたはyarnでインストールします。
npm install yup
yarn add yup
Yupのサンプルを動かす
以下は、yup.object() でユーザー登録フォームのスキーマを定義し、schema.validate() で入力値を検証するサンプルです。氏名・メールアドレス・年齢の3項目に、それぞれ required()・email()・min() / max() といったバリデーションメソッドを組み合わせています。
まず要点となるスキーマ定義部分だけを抜き出すと、次のようになります。
import * as yup from 'yup'
const schema = yup.object({
name: yup.string().required('氏名は必須です').min(1),
email: yup.string().required('メールは必須です').email('形式が不正です'),
age: yup.number().required().min(0).max(120),
})
// abortEarly: false で全項目のエラーをまとめて取得
await schema.validate(
{ name: 'たくま', email: 'takuma@example.com', age: 30 },
{ abortEarly: false }
)
実際に動かせるものが下です。フォームに入力するたびにschema.validate()が走り、エラーがあれば項目ごとに赤字で表示されます。氏名を空にしたり、メールアドレスから@を消したりすると、Yupがどう反応するか確認してみてください。
このサンプルではschema.validate(values, { abortEarly: false })を使い、最初のエラーで処理を止めずに全項目のエラーをまとめて取得しています。min()やmax()の数値を変えたり、email()をurl()に差し替えたりすると、Yupが用意しているバリデーションメソッドの範囲を体感できます。
基本的な使い方
Yupの基本は、string() や number() などのプリミティブ型スキーマに、required() や min() といった制約メソッドをチェーンして組み立てることです。
import * as yup from 'yup'
// 文字列スキーマ
const nameSchema = yup.string().required().min(2).max(20)
// 検証(同期版)
try {
nameSchema.validateSync('たく')
console.log('OK')
} catch (err) {
console.log(err.errors) // ['name must be at least 2 characters']
}
// キャスト(型変換)
const numberSchema = yup.number()
console.log(numberSchema.cast('42')) // 42(数値型に変換される)
validate() は非同期でPromiseを返し、validateSync() は同期的に例外を投げます。非同期バリデーションルールを含む場合はvalidateSync()は使えないため、通常はvalidate()を使うのが安全です。
実践的なユースケース
ネストしたオブジェクトスキーマの検証
実際のフォームでは、住所や連絡先のようにオブジェクトがネストすることがよくあります。Yupはyup.object()の中に別のyup.object()やyup.array()を入れ子にできるため、複雑な構造もそのままスキーマ化できます。
import * as yup from 'yup'
const orderSchema = yup.object({
customer: yup.object({
name: yup.string().required(),
address: yup.object({
zip: yup.string().matches(/^\d{3}-\d{4}$/, '郵便番号の形式が不正です'),
city: yup.string().required(),
}),
}),
items: yup.array(
yup.object({
name: yup.string().required(),
qty: yup.number().min(1).required(),
})
).min(1, '商品を1つ以上追加してください'),
})
array()スキーマに対してもmin()やrequired()が使え、配列の各要素にはarray(itemSchema)のように要素側のスキーマを渡します。
値のキャストとデフォルト値
Yupは検証だけでなく、値の**型変換(キャスト)**も担当できます。HTMLフォームの<input>から受け取る値は常に文字列ですが、number()やdate()スキーマにキャストさせれば、検証と同時に適切な型へ変換できます。default()で未入力時の初期値も設定できます。
数量を空欄のまま実行すると、default(1)によってquantityが自動的に1として扱われるのが分かります。cast()は検証をスキップして変換だけを行うメソッドなので、フォームの初期値整形やAPIレスポンスの正規化にも使えます。
非同期バリデーションによるカスタムルール
パスワード確認欄のように、他のフィールドの値を参照して検証したいケースや、検証処理自体を非同期にしたいケースでは、test()に非同期関数を渡します。Yupはtest()のコールバックがPromiseを返すことを検知し、validate()実行時に自動的に待機します。
ここではyup.ref('password')を使い、confirmフィールドからpasswordフィールドの値を参照して一致確認をしています。またtest()内でawaitを使った非同期処理を挟むことで、実際のAPI通信を伴うようなバリデーション(重複チェックなど)にも同じパターンを応用できます。weakPasswordsの配列に自分がよく使う文字列を足して試すと、弱いパスワード判定の挙動が変わるのが確認できます。
まとめ
Yupは、object() や string() などのプリミティブスキーマをチェーンメソッドで組み立てるだけで、必須チェック・型変換・非同期バリデーションまでを一貫して扱えるライブラリです。Formikをはじめとするフォームライブラリとの統合実績が長く、InferTypeによるTypeScriptとの連携も強力なため、フォームのバリデーションロジックを1箇所にまとめたいときの選択肢として引き続き有力です。
まずは手元の小さなフォームから、required()やmin()といった基本メソッドを使ったスキーマ定義を試してみてください。ネストしたオブジェクトや非同期ルールが必要になったタイミングで、この記事のサンプルに戻ってきていただければと思います。
