この記事に関連するツール
ブラウザ上ですぐに試せます。記事の内容を確認しながら使うと、作業の流れをつかみやすくなります。
APIレスポンスを扱うTypeScript開発で避けて通れないのが、JSONに対応する型定義です。数十行のネストしたJSONを目で追いながら interface を手書きするのは、退屈なうえにタイプミスの温床にもなります。

この記事では、実際のJSONがどんなTypeScriptの型になるのかを変換例で示しながら、自動生成のコツと注意点を解説します。
基本:フラットなオブジェクトの変換
まずは単純な例から。次のJSONを見てください。
{
"id": 42,
"name": "Alice",
"isActive": true
}
これは次のような型になります。各値の型(number / string / boolean)は、実際の値から機械的に推論できます。
interface User {
id: number;
name: string;
isActive: boolean;
}
ネストと配列を含む変換
実際のAPIレスポンスは、オブジェクトの入れ子や配列を含みます。
{
"id": 42,
"name": "Alice",
"roles": ["admin", "editor"],
"profile": {
"age": 30,
"city": "Tokyo"
}
}
配列は要素の型から string[] のように、ネストしたオブジェクトは別のinterfaceとして切り出すのが定石です。
interface Profile {
age: number;
city: string;
}
interface User {
id: number;
name: string;
roles: string[];
profile: Profile;
}
つまずきやすいポイント
null と省略可能プロパティ
JSONに null が入っている場合、その値だけからは「常にnullになりうるのか」「たまたまnullだったのか」は判断できません。
{ "nickname": null, "deletedAt": null }
機械的に変換すると nickname: null になりますが、実務では string | null や nickname?: string が正しいことがほとんどです。生成後に、APIの仕様に合わせて手で調整するのが現実的な運用です。
interface User {
nickname: string | null; // 値が来る場合もある
deletedAt?: string; // フィールド自体が無い場合もある
}
数値の文字列に注意
"price": "1980" のように、数値が文字列でラップされているAPIは珍しくありません。生成ツールはこれを string と推論します。アプリ側で計算するなら、型を number に直すか、受け取り後に変換する方針を決めておきましょう。
空配列は型が決まらない
"tags": [] のような空配列からは要素の型を推論できず、never[] や any[] になりがちです。要素のあるサンプルを使うか、生成後に string[] などへ手で指定します。
自動生成を使う手順
- ブラウザのNetworkタブやcurlの出力から、実際のレスポンスをコピーする
- JSON → TypeScript型生成ツール に貼り付ける
- ルートのinterface名を
RootからUserResponseなどに変更する nullや省略可能フィールドを仕様に合わせて調整する- プロジェクトに貼り付けて完了
ポイントは、できるだけ本番に近い、フィールドが揃ったサンプルを使うことです。サンプルが貧弱だと、省略可能フィールドや型のゆれを取りこぼします。
型だけで足りないときは Zod へ
TypeScriptの型は「コンパイル時」のチェックです。外部APIから実際に届くデータが型どおりである保証はありません。実行時にもデータの形を検証したいなら、JSON → Zodスキーマ生成 でバリデーションスキーマを作り、schema.parse(data) で入口チェックを入れるのがおすすめです。Zodなら型推論も効くため、型とバリデーションを一元管理できます。
よくある質問
生成された型のルート名を毎回変更するのが面倒です
多くのツールはルートを Root という汎用名で出力します。これはコピー後にプロジェクトの命名規則(ApiResponse、UserProfile など)へ一括置換するのが楽です。ネストしたinterface名は内容に即した名前になっていることが多いので、ルートだけ直せば十分なケースがほとんどです。
snake_case のAPIをcamelCaseで使いたい
生成される型はJSONのキーをそのまま反映するため、created_at のような名前になります。アプリ全体をcamelCaseで統一したい場合は、API境界で変換する(マッピング関数やcamelize系ライブラリを使う)のが定石です。型定義はAPIの実体に合わせ、変換は明示的に行うと混乱しません。
TypeScriptの型とZodスキーマ、どちらを先に作るべき?
実行時バリデーションが必要なら、Zodスキーマを作って z.infer で型を導出する方法が一元管理できておすすめです。型チェックだけで十分な内部データなら、TypeScript型の生成だけで構いません。外部APIやフォーム入力など「信頼できない入力」にはZodを使うと安全です。