コンテンツへスキップ
Tutorial

TypeScript インターフェイスを手動で記述するのをやめ、JSON から自動生成します。

| 5 min read

Botoi JSON to TypeScript API を使用して、単一の POST リクエストで任意の JSON ペイロードから正確な TypeScript インターフェイスと Zod スキーマを生成します。

TypeScript interface definition in an editor
Photo by Safar Safarov on Unsplash

新しい API を統合するたびに、JSON 応答を見つめてインターフェイスを手で入力することになります。 フィールドごとに。 どの値がオプションであるかを推測します。 それを忘れて created_at は日付ではなく文字列です。 実際の応答と一致する場合も一致しない場合もあるドキュメントからのコピーアンドペースト。

これは面倒で時間がかかり、信頼できるバグの原因となります。 JSON には、必要なすべての型がすでに含まれています。 単一の API 呼び出しでそれらを抽出できます。

1 つの POST リクエスト、1 つの TypeScript インターフェイス

任意の JSON オブジェクトを Botoi に送信します json-to-typescript ルートインターフェイスの名前を持つエンドポイント。 API は、完全な TypeScript インターフェイスを文字列として返します。

curl -X POST https://api.botoi.com/v1/schema/json-to-typescript \\
  -H "Content-Type: application/json" \\
  -d '{
    "json": {
      "id": 1,
      "name": "Acme Corp",
      "active": true,
      "tags": ["saas", "b2b"]
    },
    "name": "Company"
  }'

応答:

{
  "success": true,
  "data": {
    "typescript": "interface Company {\\n  id: number;\\n  name: string;\\n  active: boolean;\\n  tags: string[];\\n}",
    "name": "Company"
  }
}

生成されたインターフェイスの形式は次のとおりです。

interface Company {
  id: number;
  name: string;
  active: boolean;
  tags: string[];
}

API は推測します numberstringboolean、 そして string[] 価値観から。 手動の注釈はありません。 推測はできません。

プロジェクト用の type-from-API スクリプトを構築する

インターフェイスを手で入力するのは 1 回だけで済みます。 より良いアプローチ: ライブ API 応答を取得するスクリプト そして、リポジトリにコミットできるタイプ ファイルを生成します。

以下は、任意の URL から TypeScript 型を生成する bash スクリプトです。

#!/bin/bash
set -euo pipefail

API="https://api.botoi.com/v1/schema/json-to-typescript"
OUT_DIR="./src/types/generated"
mkdir -p "\$OUT_DIR"

generate_type() {
  local url="\$1"
  local name="\$2"
  local file="\$3"

  echo "Fetching \$url ..."
  local json
  json=\$(curl -s "\$url")

  echo "Generating \$name interface..."
  local result
  result=\$(curl -s -X POST "\$API" \\
    -H "Content-Type: application/json" \\
    -d "{\"json\": \$json, \"name\": \"\$name\"}")

  echo "\$result" | jq -r '.data.typescript' > "\$OUT_DIR/\$file"
  echo "Wrote \$OUT_DIR/\$file"
}

generate_type "https://api.github.com/users/octocat" "GitHubUser" "github-user.ts"
generate_type "https://jsonplaceholder.typicode.com/posts/1" "BlogPost" "blog-post.ts"

echo "Done. All types written to \$OUT_DIR/"

このスクリプトは、開発中またはコミット前のフックとして実行します。 上流の API が変更されると、 スクリプトを再実行すると、型は正確なままになります。

bash よりも Node.js を好む場合:

import { writeFileSync, mkdirSync } from "fs";

const API = "https://api.botoi.com/v1/schema/json-to-typescript";

async function generateType(json: unknown, name: string): Promise<string> {
  const res = await fetch(API, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ json, name }),
  });
  const data = await res.json();
  return data.data.typescript;
}

async function main() {
  const userRes = await fetch("https://api.github.com/users/octocat");
  const userJson = await userRes.json();

  const typescript = await generateType(userJson, "GitHubUser");

  mkdirSync("./src/types/generated", { recursive: true });
  writeFileSync("./src/types/generated/github-user.ts", typescript);
  console.log("Wrote ./src/types/generated/github-user.ts");
}

main();

実際の例: GitHub API ユーザー応答のタイプを生成する

GitHub /users/:username エンドポイントは 30 以上のフィールドを返します。 そのインターフェースを手作業で書く 数分かかり、タイプミスを招きます。 ここでは 2 段階のアプローチを示します。

# Fetch the GitHub user JSON
GITHUB_JSON=\$(curl -s https://api.github.com/users/octocat)

# Send it to the Botoi API
curl -s -X POST https://api.botoi.com/v1/schema/json-to-typescript \\
  -H "Content-Type: application/json" \\
  -d "{\"json\": \$GITHUB_JSON, \"name\": \"GitHubUser\"}" \\
  | jq -r '.data.typescript'

出力:

interface GitHubUser {
  login: string;
  id: number;
  node_id: string;
  avatar_url: string;
  gravatar_id: string;
  url: string;
  html_url: string;
  followers_url: string;
  following_url: string;
  gists_url: string;
  starred_url: string;
  subscriptions_url: string;
  organizations_url: string;
  repos_url: string;
  events_url: string;
  received_events_url: string;
  type: string;
  site_admin: boolean;
  name: string;
  company: string;
  blog: string;
  location: string;
  bio: string;
  twitter_username: string;
  public_repos: number;
  public_gists: number;
  followers: number;
  following: number;
  created_at: string;
  updated_at: string;
}

つまり、32 個のフィールドを正しく入力すると、1 秒以内に入力されます。 出力をファイルにパイプすると、次のようになります。 本番環境で使用できる型定義。

代わりに Zod スキーマを生成する

TypeScript インターフェイスはコンパイル時の安全性を提供しますが、実行時には失われます。 実行時検証が必要な場合は、 の json-to-zod エンドポイントは、同じ JSON 入力から Zod スキーマを生成します。

curl -s -X POST https://api.botoi.com/v1/schema/json-to-zod \\
  -H "Content-Type: application/json" \\
  -d '{
    "json": {
      "id": 1,
      "name": "Acme Corp",
      "active": true,
      "tags": ["saas", "b2b"]
    },
    "name": "Company"
  }' | jq -r '.data.zod'

出力:

import { z } from "zod";

const Company = z.object({
  id: z.number(),
  name: z.string(),
  active: z.boolean(),
  tags: z.array(z.string()),
});

生成されたスキーマをコードベースにドロップすると、実行時の検証と型推論の両方が得られます。

import { z } from "zod";

const Company = z.object({
  id: z.number(),
  name: z.string(),
  active: z.boolean(),
  tags: z.array(z.string()),
});

type Company = z.infer<typeof Company>;

const parsed = Company.parse(apiResponse);
// parsed is fully typed and validated at runtime

Zod を使用すると、アプリケーション ロジックの奥深くでサイレント バグが発生するのではなく、無効なデータが境界にスローされます。

各エンドポイントをいつ使用するか

シナリオ 終点 なぜ
信頼できる内部 API 応答 json-to-typescript 軽量; ランタイムコストがかからない
外部 API 応答 json-to-zod 境界でデータを検証します
フォーム入力またはユーザーが送信したデータ json-to-zod 解析する、検証しない
素早いプロトタイピング json-to-typescript 型付きコードへの最速パス
CIパイプラインタイプの生成 どちらか どちらも確定的な出力を生成します

重要なポイント

  • 1 つのリクエストが手動入力を置き換えます。 JSON を送信し、TypeScript インターフェイスまたは Zod スキーマを取得します。
  • それを自動化しましょう。 アップストリーム API が変更されるたびに型を再生成するスクリプトをプロジェクトに追加します。
  • アカウントは必要ありません。 無料枠では、サインアップなしで 1 分あたり 5 件のリクエストが可能です。
  • あらゆる JSON ソースで動作します。 REST API、構成ファイル、データベースのエクスポート、Webhook ペイロード。

完全な API ドキュメント カバー 追加のスキーマ エンドポイント (以下を含む) json-to-jsonschema JSON スキーマ出力の場合。

FAQ

API はどのような JSON 構造をサポートしていますか?
API は、ネストされたオブジェクト、配列、混合型配列、null、および深くネストされた構造を処理します。 null が存在する場合はオプションのフィールドも含め、各値の正しい TypeScript 型を推論します。
API キーは必要ですか?
いいえ。匿名アクセスは、IP ベースのレート制限により、1 分あたり 5 リクエストまで許可されます。 より大量の場合は、botoi.com/api で API キーにサインアップしてください。
TypeScript インターフェイスの代わりに Zod スキーマを生成できますか?
はい。 同じ JSON 本文を POST https://api.botoi.com/v1/schema/json-to-zod に送信すると、プロジェクトにドロップできる Zod スキーマ文字列が得られます。
API は型が混在した配列をどのように処理しますか?
配列に異なる型の値が含まれている場合、API は共用体型を生成します。 たとえば、文字列と数値を含む配列は (string |number)[] となります。
これを CI パイプラインで使用できますか?
はい。 API は標準の HTTP POST エンドポイントです。 任意のシェル スクリプト、GitHub アクション、またはビルド ステップから呼び出して、型定義をアップストリーム API 応答と同期させます。

botoiで開発を始めよう

150以上のAPIエンドポイント。検索、テキスト処理、画像生成、開発者ユーティリティに対応。無料プラン、クレジットカード不要。