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

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

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? フィルタリング