1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

zodで、セレクトした項目によってinput内容を変えてバリデーションする方法

Posted at

たとえば、顧客タイプが 'individual'(個人)の場合は companyName(会社名)は任意、'business'(法人)の場合は必須とする例になります。

1. discriminated union を使う方法

Zod の discriminated union を使うと、customerType の値ごとにスキーマを分けることができます。以下の例では、'individual' の場合は companyName が任意、'business' の場合は companyName が必須となります。

import { z } from 'zod';

const individualSchema = z.object({
  customerType: z.literal('individual'),
  companyName: z.string().optional(),
});

const businessSchema = z.object({
  customerType: z.literal('business'),
  companyName: z.string().nonempty('会社名は必須です。'),
});

const schema = z.discriminatedUnion('customerType', [
  individualSchema,
  businessSchema,
]);

// テスト例
console.log(schema.safeParse({ customerType: 'individual' })); // OK
console.log(schema.safeParse({ customerType: 'business', companyName: '' })); // エラー
この方法は各ケースごとに独立したスキーマを定義できるため読みやすく保守しやすいメリットがあります

2. 各フィールドに refine を使う方法

companyName フィールドに対して .refine() を適用し、ctx.parent(親オブジェクト)を利用して条件付きバリデーションを実装する方法もあります。以下の例では、customerType が 'business' の場合のみ companyName の入力内容をチェックします。

import { z } from 'zod';

const schema = z.object({
  customerType: z.enum(['individual', 'business']),
  companyName: z.string().optional().refine((value, ctx) => {
    // customerType が 'business' の場合のみ companyName の中身をチェック
    if (ctx.parent.customerType === 'business') {
      return value !== undefined && value.trim() !== '';
    }
    return true; // それ以外の場合は常に OK
  }, {
    message: '会社名は必須です。',
    path: ['companyName'],
  }),
});

// テスト例
console.log(schema.safeParse({ customerType: 'individual' })); // OK
console.log(schema.safeParse({ customerType: 'business', companyName: '' })); // エラー

この方法は、ひとつのスキーマ定義内で完結できるため、コード量を減らしたい場合に有効ですが、ctx.parent を利用している点や条件分岐が複雑になるとロジックの把握が難しくなる可能性があります。

どちらの方法も一長一短がありますので、プロジェクトの規模やコードの見通しやすさに応じて、適切な方法を選んでください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?