💎

Zodを使ったTypeScriptでのバリデーション方法についてわかりやすく解説

2024/04/19に公開

こんにちは。masakiです。
今回は、Zodを使ったTypeScriptでのバリデーション方法についてわかりやすく解説します。

Zodとは

Zodについて知らない方のために、Zodとは何かについて簡単に説明しておきます。

Zodは、JavaScriptもしくはTypeScriptで用いるバリデーションのライブラリです。
Zodを使うと、簡単にバリデーションの実装を行うことができます。

僕は現在は仕事でVueを使っているのですが、VueだとVeeValidateやVuelidateなどのライブラリが使いにくくて微妙なので、Zodを用いることをオススメします。

Zodを使ったバリデーションの方法

まずはおなじみのコマンドを実行します。

npm i zod

Zodを使うための準備はこれだけです。

スキーマの作成

今回は、例として簡単なログイン画面を作成し、メールアドレスとパスワードをバリデーションしてみます。
まずはスキーマの作成をします。useUserValidation.tsというファイルを作成し、以下のように記述します。

import { z } from 'zod'

const userSchema = z.object({
  email: z
    .string()
    .email(),
  password: z
    .string()
    .min(8)
    .max(16)
    .refine(
      (val) => {
        return /^[A-Za-z0-9]*$/.test(val)
      }
    )
})

今回はVue3のcomposition関数を用いて作っていきますが、Reactなどを使われている方でも読み替えられるかと思います。

ここでは、userSchemaというスキーマを作成しています。
スキーマとは、どのようなバリデーションを行うのかの設定のことになります。

以下、用いているメソッドの説明です。

string()

バリデーション対象が文字列であることを示します。

email()

メールアドレスであるかどうかバリデーションします。
ここで、メールアドレスかどうかをどうやって判定しているのか疑問がわくと思います。

僕が調べたところ、xxx@xx.xxのような形式かどうかを判定しているシンプルなもののようです。
もう少し厳格にバリデーションしたい場合は、正規表現を使って独自にバリデーションを実施する必要があります。
※Zodでの正規表現の使い方についても後ほど解説します。

min()

例えば、min(8)であれば、文字列が最低でも8文字以上あるかどうかをバリデーションします。

max()

こちらはmin()と考え方は同じなので割愛します。

refine()

refine()は、独自にバリデーションの関数を設定できます。上記のコードの中の

refine(
  (val) => {
    return /^[A-Za-z0-9]*$/.test(val)
  }
)

では、入力された文字列が英語の大文字、英語の小文字、数字で構成されているかどうかを判定します。
例えば、"aaaa1111"や"Aaaa1111"は問題ないですが、"Aaaa_111"とかはNGです。

他にも様々なメソッドがあるので、もっと詳しく知りたい方は公式ドキュメントをご覧ください。
»Zod 公式ドキュメント

バリデーションの作成

上記では、あくまでスキーマを定義しただけなので、まだバリデーションの関数を作れていません。

バリデーションの関数は、以下のように作ります。
先ほどのuseUserValidation.tsに続けて書いてください。

// スキーマを使用して型を定義
type User = z.infer<typeof userSchema>

export const useUserValidation = () => {
  const errors = ref<Object | null>(null)

  const validate = (data: User) => {
    try {
      userSchema.parse(data)
    } catch (error: unknown) {
      if (error instanceof z.ZodError) {
        errors.value = error.flatten()?.fieldErrors
      }
    }
  }

  return { errors, validate }
}

ここでも、いくつか重要なメソッドやキーワードを解説していきます。

infer

inferは、スキーマから型定義を予測するキーワードになります。
TypeScriptを用いている場合には、こちらを使うと型をラクに用いることができます。

今回は、emailとpasswordをプロパティに持ったオブジェクトの型をUser型として作成しています。
バリデーションの関数に渡す引数はUser型のオブジェクトなので、そこでUser型を用いていきます。

parse()

parse()は、スキーマで定義したバリデーションを実際に実行するメソッドです。
バリデーションが不正だった場合は、エラーを返すので、try, catchでcatchしてエラーハンドリングする必要があります。

ちなみに、ZodにはsafeParse()というメソッドもあります。こちらは、バリデーションの結果やエラーメッセージなどをオブジェクトで返すメソッドになります。
イメージとしてはこんな感じの結果が返ってきます。

{success: true, data: 'john@example.com'}

safeParse()を用いる場合は、仮にバリデーションが不正になっていたとしても、try, catchで囲む必要はありません。

Xについて

僕のXアカウントでは、主にweb開発、AI、会社経営のノウハウについて発信しています。もし興味があれば、フォローしていただけると嬉しいです。

プログラミング学習サポート&キャリア相談について

プログラミング学習サポート&キャリア相談も始めました。興味のある方はこちらから詳細をご覧ください。
https://shibayama-masaki.com/consulting/

Discussion