Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Zodのデータ変換が便利すぎた。 しかし使いすぎで苦しくなっていった話

Zodのデータ変換が便利すぎた。 しかし使いすぎで苦しくなっていった話

フロントエンドカンファレンス名古屋のLT登壇資料です。

Avatar for Melonps

Melonps

May 09, 2026

More Decks by Melonps

Other Decks in Technology

Transcript

  1. スキーマ定義にどこまで書くか? ◎Zodで型定義とバリデーションと両立させて使う形が多い 3 const UserSchema = z.object({ name: z.string(), age:

    z.number().min(0), email: z.email(), }); const result = UserSchema.safeParse({ name: "太郎", age: 1000, email: "[email protected]", }); console.log(result.success, result.data) スキーマ定義(TS) パースによるランタイムでの検証 APIレスポンスの検証やフォーム入力制御で活躍
  2. データ変換ツールとしても進化してきた .transform():バリデーション後に型変換 4 const NameLengthSchema = z.string().transform((val) => val.length); type

    Input = z.input<typeof NameLengthSchema>; type Output = z.output<typeof NameLengthSchema>; .pipe():変換後の値に再バリデーション const SafeStringToNumber = z.string() .transform((value) => Number(value)) .pipe(z.number().min(0).max(100)); numberが確定 0~100が確定
  3. 便利だった 便利だった実装:APIレスポンスの入り口 6 const EventSchema = z.object({ startAt: z.iso.datetime().transform((val) =>

    new Date(val)), endAt: z.iso.datetime().transform((val) => new Date(val)), }).refine((data) => data.endAt.getTime() > data.startAt.getTime(), { message: "終了時刻は開始時刻より後に設定してください", path: ["endAt"], }); ◎APIから得たデータの論理と型の検証をする 論理の保証 ルールの整備がないままtransform化が進んでいった Date型へ変換
  4. 苦しくなった const EventSchema = z.object({ startAt: z.iso.datetime().transform((val) => new Date(val)),

    endAt: z.iso.datetime().transform((val) => new Date(val)), attendees: z.array(z.object({ name: z.string(), role: z.string() })), }).transform((event) => ({ ...event, duration: event.endAt.getTime() - event.startAt.getTime(), activeAttendees: event.attendees.filter((a) => a.role !== "observer"), })); 苦しくなっていった実装 7 ◎データクレンジングや表示用の変換を持ち始めた →スキーマを追加するごとに、テストや議論が必要な状態に... 表示用の変換 useFormに渡す型はIn?Out? フィルタリング