Zod:validation
2026年5月1日zodを使わなくても
inputタグのtypeをemailやurlにしたり、min/maxの指定はできるが、inputタグのvalidationはクライアントサイドだけなのでセキュリティ面を考えるとサーバー側でも検証をする必要があるzodによる検証で問題が発生するケースもある。例えばHTMLタグや特殊文字がstringの文章に含まれている場合、意図せずvalidationに引っかかる。
npm i zod使い方
schemaを定義
const postSchema = z.object({
title: z.string().min(1).max(30),
url: z.string().url(),
});検証したいオブジェクトを作成
const rawData = {
title: formData.get("title"),
url: formData.get("url"),
};safeParse()
const paredData = postSchema.safeParse(rawData);
if (!paredData.success) {
return { success: false, message: "error submit form" };
}結果のオブジェクトは
{ success: boolean, data?, error? }という形成功の場合はdataに
parse()に渡したオブジェクトが入る。 失敗だとerrorのオブジェクト
parseに使うのは基本的に
parse()ではなくsafeParse()で良い
エラー処理:
parse():失敗時に例外を投げるのでtry/catchでcatchに流さないとアプリが止まる。safeParse():例外を投げないのでtry/catch以外で使える。try/catchで使う場合はsuccessで判定しないとcatchに流れない。
用語:
オブジェクトの要素の schema は「文字列スキーマ」
オブジェクト自体の schema は「オブジェクトスキーマ」
共通するschemaがある場合
例えばemail , password までは共通だが、その他のフィールドは異なる2つのオブジェクトスキーマを作成する場合
変数
import { z } from "zod";
const emailSchema = z.string().email();
const passwordSchema = z.string().min(8);
// フォーム A
const loginSchema = z.object({
email: emailSchema,
password: passwordSchema,
memo: z.string().optional(),
});
// フォーム B
const signupSchema = z.object({
email: emailSchema,
password: passwordSchema,
url: z.string().url("Invalid URL"),
});extend
import { z } from "zod";
const emailSchema = z.string().email();
const passwordSchema = z.string().min(8);
// ベース
const baseSchema = z.object({
email: emailSchema,
password: passwordSchema,
url: z.string().url("Invalid URL"),
});
// ベースを拡張
const extendedSchema = baseSchema.extend({
memo: z.string().optional(),
});extend()はschemaの拡張だけでなく合成にも使える。
const contentSchema = z.object({
id: z.number(),
title: z.string(),
});
const userSchema = z.object({
name: z.string(),
email: z.email(),
});
const authorSchema = z.object({
author: z.string(),
});
const postSchema = contentSchema.extend({
...userSchema.shape,
...authorSchema.shape,
});z.infer
export const reviewSchema = z.object({
title: z.string().min(1, "Title is required"),
rating: z.number().min(1).max(5),
});
export type ReviewFormType = z.infer<typeof reviewSchema>;z.infer<typeof schemaName>を使うことでオブジェクトスキーマから型を作成できる。型の二重定義が必要無くなる、変更箇所が1つで済む等のメリットがある。
const [formState, setFormState] = useState<ReviewFormType>({
title: "",
rating: 3,
});javascript
/security