はじめに
Nextjs で fetch を使う際に、型安全にするために zod を使ってみました。
json を取得する際に、型を定義して、それに基づいてバリデーションを行うことができます。
環境
- Next.js:
14.2.2
- zod:
^3.23.5
背景
Nextjs で ラップされたfetch を使う際に、型安全にしたいけど、json()
を使うと型がany
になってしまうので、zod を使って型安全にしたいと思いました。
zod とは
zod は、スキーマを使って型を定義し、それに基づいてバリデーションを行うライブラリです。
zod の例
import { z } from "zod";
const UserSchema = z.object({
name: z.string(),
age: z.number(),
});
const user = {
name: "John",
age: 30,
};
const parsed = UserSchema.safeParse(user);
if (!parsed.success) return parsed.error;
console.log(parsed.data); // { name: 'John', age: 30 }
zod で safeParse できない場合
例えば、age
が string
だった場合、以下のようなエラーが出ます。
import { z } from "zod";
const UserSchema = z.object({
name: z.string(),
age: z.number(),
});
const user = {
name: "John",
age: "30", // string になっている
};
console.log(UserSchema.safeParse(user));
// { success: false, error: [ZodError [ { message: 'Invalid input', path: [ 'age' ], ... } ] }
1. よくある fetch で json を取得するコード
const res = await fetch("http://localhost:3001/user/1");
const user = await res.json();
// ^? user any
このままではuser
の型が any
になってしまいます。
2. 自分で型を定義して、as
を使うパターン
type User = {
name: string;
age: number;
}
const res = await fetch("http://localhost:3001/user/1");
const user = await res.json() as User;
// ^? const users: User
この方法もありますが、User
の型が変わった場合、全ての箇所を修正する必要があります。
3. zod を使って型安全にする
import { z } from "zod";
const UserSchema = z.object({
name: z.string(),
age: z.number(),
});
const res = await fetch("http://localhost:3001/user/1")
.then((res) => res.json())
.then(UserSchema.safeParse); // any → User
if (!res.success) return res.error;
const user = res.data;
// ^? const user: { name: string; age: number; }
このように、safeParse を使うことで、型安全 & 自分の欲しいデータの形で運用 & エラーハンドリングを行うことができました。
参考
Matpocock さんの動画だったと思うのですが失念しました。。。すみません