LoginSignup
1
1

TypeScript ファーストの型検証ライブラリ「Zod」とは?

Posted at

はじめに

Next.jsのチューリアル第12章をやっているときに、Zodというライブラリを使っていました。

何のことか分からなかったので調べることにしました。

Zodとは

TypeScriptにおける型の検証を簡単にしてくれるライブラリです。


以下のコードはNext.jsチュートリアルの第12章で実際に記述されているコードです。

この記事ではこのコードをもとにZodを学びます。

/app/lib/actions.ts
'use server';
 
import { z } from 'zod';
 
const FormSchema = z.object({
  id: z.string(),
  customerId: z.string(),
  amount: z.coerce.number(),
  status: z.enum(['pending', 'paid']),
  date: z.string(),
});
 
const CreateInvoice = FormSchema.omit({ id: true, date: true });

export async function createInvoice(formData: FormData) {
  const rawFormData = CreateInvoice.parse({
    customerId: formData.get('customerId'),
    amount: formData.get('amount'),
    status: formData.get('status'),
  });
}

使用するコードの説明

上のコードの意味が分かってないと頭に入ってこないと思うので最初にそこを説明します。

createInvoiceという関数は新しいデータ(請求書)を作成しようとしている関数です。

このコードでは、フォームから受け取った値をrawFormDataに格納しているだけです。

実際のフォームが以下の画像です。

image.png

<form />タグ内には以下の要素があります。

  • nameにcustomerIdを持った<select />タグ
  • nameにamoutを持った<input />タグ
  • nameにstatusを持った<input />タグ

以下コンソールにrawFormDataを出力した場合の例

コンソール
{
  customerId: '13d07535-c59e-4157-a011-f8d2ef4e0cbb',
  amount: 234,
  status: 'pending'
}

Zodを使って型検証をしよう

それではZodの説明を始めましょう。

まずインストールですね。

ターミナル
npm install zod       # npm
yarn add zod          # yarn
bun add zod           # bun
pnpm add zod          # pnpm

そして、見やすいようにもう一度使用するコードを貼っておきます。

/app/lib/actions.ts
'use server';
 
import { z } from 'zod';
 
const FormSchema = z.object({
  id: z.string(),
  customerId: z.string(),
  amount: z.coerce.number(),
  status: z.enum(['pending', 'paid']),
  date: z.string(),
});
 
const CreateInvoice = FormSchema.omit({ id: true, date: true });

export async function createInvoice(formData: FormData) {
  const rawFormData = CreateInvoice.parse({
    customerId: formData.get('customerId'),
    amount: formData.get('amount'),
    status: formData.get('status'),
  });
}

import

{ z }としてimportするみたいですね。

1文字だけでimportするという仕方で違和感を覚えました。

import { z } from 'zod';

スキーマの宣言

例えばstring型のスキーマを宣言したい場合は、

const TestSchema = z.string()

とするみたいですね。

object

今回は受け取ったフォームの情報をrawFormDataというオブジェクトに変換するのでz.objectを付けます。

const FormSchema = z.object({});

string

idcustomerIddatestringとして扱うのでz.string()を付けます。

const FormSchema = z.object({
+ id: z.string(),
+ customerId: z.string(),


+ date: z.string(),
});

number

amountnumberとして扱うのでz.number()を付けます。

気になっているであろうcoerceは下で解説します。

const FormSchema = z.object({
  id: z.string(),
  customerId: z.string(),
+ amount: z.coerce.number(),

  date: z.string(),
});

coerce

coerceではデータの変換をすることができます。

フォームから送信されるデータは、基本的にはすべて文字列として扱われます。

ですが、amountnumberとして扱いたいので、coerce.numberを付けて変換しているというわけですね。

const FormSchema = z.object({
  id: z.string(),
  customerId: z.string(),
+ amount: z.coerce.number(),

  date: z.string(),
});

enum

statuspendingまたはpaidという文字列のみ許可するようにしたいです。

その時には、z.enumを使うことで、列挙した文字列のうちいずれかの値であれば許可をすることができます。

Typescriptでいう"foo" | "baz"みたいな感じですね。

const FormSchema = z.object({
  id: z.string(),
  customerId: z.string(),
  amount: z.coerce.number(),
+ status: z.enum(['pending', 'paid']),
  date: z.string(),
});

omit

omitを使用すると宣言したスキーマから一部を削除することができます。

この場合、FormSchemaiddateは必要ないので、それぞれをtrueとすることで削除ができるようです。

const CreateInvoice = FormSchema.omit({ id: true, date: true });

スキーマを使って検証 parse

完成したスキーマCreateInvoiceを使って検証しましょう。

スキーマ.parse(検証したい値)とすることで検証ができます。

export async function createInvoice(formData: FormData) {
  const rawFormData = CreateInvoice.parse({  // parse
    customerId: formData.get('customerId'),
    amount: formData.get('amount'),
    status: formData.get('status'),
  });
}

検証がtrueだった場合は問題なくrawFormDataにオブジェクトが代入されます。

検証がfalseだった場合はエラーになります。

おわりに

おそらくエラーハンドリングもするべきなんでしょうけど、Nextチュートリアルの第13章で触れるみたいなのでその後追記します。

参考

1
1
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
1