はじめに
この記事は、Techouse Advent Calendar 2024 8日目です。
昨日は 澤井(aaaa777) さんによる 配属1ヶ月のインターンが勝手にRBS::Inlineを導入して怒られた でした。
8日目は、高橋 (@Kaffff) が担当します。今回は、localStorage に保存された値を検証する場面で、Zod の parse 関数を利用した方法を紹介します。
筆者はこれまで localStorage から取得した値のパースに、JSON.parse
を使っていましたが、Zod の parse 関数と組み合わせることで、より型安全に値をパースできました。
従来の方法 (JSON.parse のみを使う方法)
まずは、JSON.parse
のみを使った従来の方法を確認してみましょう。
まず、保存したいデータの型を定義します。ここでは、User
型を定義しています。
type User = { name: string; age: number };
localStorage には文字列しか保存できないため、オブジェクトを保存する際には JSON.stringify
を使って JSON 文字列に変換する必要があります。
const user: User = { name: "山田 太郎", age: 20 }; localStorage.setItem("user", JSON.stringify(user));
保存した値を取得する際は、localStorage.getItem
を使ってデータを取得します。localStorage.getItem
で取得した値は文字列なので、JSON.parse
を使ってオブジェクトに戻します。
ただし、この操作には注意が必要です。万が一、localStorage に格納されている値が JSON 形式ではなかった場合、エラーが発生します。
以下のコードでは、もしパースに失敗した場合には catch 節でエラーをキャッチし、localStorage の値を削除しています。
const item = localStorage.getItem("user") ?? "{}"; try { const user = JSON.parse(item) as User; } catch { // パースに失敗した場合は localStorage の値を削除する localStorage.removeItem("user"); }
問題点
この方法で問題になるのは、型安全が保証されないことです。JSON.parse
の結果として返される値は、型が保証されていません。そのため、型の不一致や予期しない構造のデータを扱う場合にバグが発生する可能性があります。
Zod を組み合わせた方法
そこで登場するのが、Zod です。 Zod とは TypeScript 向けのスキーマ宣言およびバリデーションを行うためのライブラリです。
Zod を使う場合、まずスキーマを定義します。ここでは z.object()
や z.string()
等を用いて、ユーザーのスキーマを定義しています。
次の type User = z.infer<typeof userSchema>
では、Zod のスキーマから TypeScript の User
型を抽出しています。
import { z } from "zod"; const userSchema = z.object({ name: z.string(), age: z.number(), }); type User = z.infer<typeof userSchema>;
localStorage にデータを保存する部分は、従来の方法と変わりません。
const user: User = { name: "山田 太郎", age: 20 }; localStorage.setItem("user", JSON.stringify(user));
localStorage から値を取得し、Zod でバリデーションを行うコードは以下のようになります。
ここでは、userSchema.parse
を使って、JSON.parse
した値がスキーマに従っているかを検証しています。
もし検証に失敗した場合は、ZodError
を投げます。
const item = localStorage.getItem("user") ?? "{}"; try { const parsedItem = JSON.parse(item); const user = userSchema.parse(parsedItem); } catch { // パースに失敗した場合は loclaStorage の値を削除する localStorage.removeItem("user"); }
JSON.parse との比較
JSON.parse
は単に JSON 文字列 を JavaScript オブジェクトに変換するためのもので、データ型が適切かどうかは検証しません。
データが JSON 形式でない場合はエラーを投げますが、それ以外のバリデーションは行いません。
一方で、Zod の parse
は、与えられたデータがスキーマに従っているかどうかを検証します。
特徴 | JSON.parse | Zod の parse |
---|---|---|
目的 | JSON 文字列を JavaScript オブジェクトに変換 | データがスキーマに適合するか検証する |
バリデーション | JSON 構文が正しいかどうかだけ確認 | 型や制約のバリデーションを実施 |
エラー処理 | JSON が無効な場合、SyntaxError が投げられる |
バリデーションエラーがある場合、ZodError が投げられる |
戻り値 | 有効な JSON 文字列から変換されたオブジェクト(any 型) |
スキーマに一致するデータ (型はスキーマから生成される) |
まとめ
普段、フォームのバリデーションに用いることが多い Zod ですが、フォームだけでなく localStorage や URL などアプリケーション外部からの入力全般に用いることができる非常に有用なライブラリです。
Zod を使用することで、型安全なコードを書き、バグのリスクを減らすことができます。ぜひ、皆さんも試してみてください。
最後まで読んでいただき、ありがとうございました。参考になれば幸いです!
明日のTechouse Advent Calendar 2024は titti-008 さんによる 資料作成ゼロ!ChatGPTで効率化する勉強会運営の秘密 です。
Techouse では、社会課題の解決に一緒に取り組むエンジニアを募集しております。 ご応募お待ちしております。