本文へスキップ

TypeScriptからZodスキーマへの変換器 — Numio

ts-to-zod を使って TypeScript の interface と型から Zod スキーマを生成します。型 Foo はそれぞれエクスポートされる fooSchema になり、@format email や @minimum などの JSDoc タグは Zod のバリデーターになります。

API の型がすでに TypeScript の interface として存在し、スキーマを手書きせずに受信リクエストを実行時に検証したい場合。

TypeScript

Zod Schema

こんなときに使えます

  • API の型がすでに TypeScript の interface として存在し、スキーマを手書きせずに受信リクエストを実行時に検証したい場合。
  • フォーム入力を Zod で検証しており、スキーマを共有の TypeScript 型と一致させておきたい場合。

使い方

  1. TypeScript の interface か型エイリアスを貼り付けます。@minimum 13 や @format email などの JSDoc タグを付けるとバリデーターが生成されます。
  2. 設定で Keep TSDoc Comments をオンにするとコメントが出力にコピーされ、Skip the creation of zod validators from JSDoc annotations をオンにするとタグが無視されます。
  3. ソースは /api/typescript-to-zod 経由でサーバー上で変換されます。"zod" から z をインポートするコードをコピーします。

TypeScript

export interface Signup {
  /**
   * @format email
   */
  email: string;
  /**
   * @minimum 13
   * @maximum 120
   */
  age: number;
  plan: "free" | "pro";
  referrer?: string | null;
  createdAt: Date;
}

Zod スキーマ

import { z } from "zod"

export const signupSchema = z.object({
  email: z.string().email(),
  age: z.number().min(13).max(120),
  plan: z.union([z.literal("free"), z.literal("pro")]),
  referrer: z.string().optional().nullable(),
  createdAt: z.date(),
})

仕様と制限

入力は変換のためにサーバーのルート(/api/typescript-to-zod)に送信されます。ブラウザ内だけで処理されるわけではありません。Next.js の API ルートが受け付けるリクエストボディは、デフォルトで 1 MB までです。

変換されるのは型だけです。エクスポートされた関数や定数からはスキーマは生成されません。

入力にない型を参照している型があると、コンバーターはスキーマを出力せずに依存関係の不足エラーを報告します。

スキーマは依存関係の順に並ぶため、Author のように参照される型は、それを使う型より先に出力されます。

FAQ

省略可能なフィールドと null のフィールドはどう変換されますか?

referrer?: string | null は z.string().optional().nullable() に、型が Author | null のプロパティは authorSchema.nullable() になります。

Date はどう扱われますか?

Date プロパティは z.date() になり、ISO 文字列ではなく Date オブジェクトを受け付けます。JSON の入力には z.coerce.date() を使ってください。

"Some schemas can't be generated due to direct or indirect missing dependencies" と表示されるのはなぜですか?

ある型が、貼り付けたコードにない別の型を参照しています。参照先の型も貼り付けてください。

仕様を確認する