跳转到内容
Tutorial

停止手动编写 TypeScript 接口:从 JSON 自动生成它们

| 5 min read

使用 Botoi JSON 到 TypeScript API 从单个 POST 请求中的任何 JSON 负载生成准确的 TypeScript 接口和 Zod 架构。

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

每次集成新的 API 时,您最终都会盯着 JSON 响应并手动输入界面。 逐个领域。 猜测哪些值是可选的。 忘记了 created_at 是一个字符串,而不是日期。 从可能或可能不匹配真实响应的文档中复制粘贴。

这是乏味、缓慢且可靠的错误来源。 JSON 已包含您需要的每种类型。 单个 API 调用即可提取它们。

一个 POST 请求,一个 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 推断 number, string, boolean, 和 string[] 来自价值观。 无需手动注释。 无需猜测。

为您的项目构建 types-from-api 脚本

手动输入界面是一次性解决方法。 更好的方法:获取实时 API 响应的脚本 并生成您可以提交到您的存储库的类型文件。

下面是一个 bash 脚本,可以从任何 URL 生成 TypeScript 类型:

#!/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发生变化时, 重新运行脚本,您的类型保持准确。

如果您更喜欢 Node.js 而不是 bash:

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 多个字段。 手动编写该界面 需要几分钟并且容易出现拼写错误。 这是两步方法:

# 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 个字段,如果输入正确,只需不到一秒的时间。 将输出通过管道传输到文件中,您就得到了 生产就绪的类型定义。

改为生成 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 管道类型生成 任何一个 两者都会产生确定性的输出

要点

  • 一个请求取代了手动输入。 发送 JSON,获取 TypeScript 接口或 Zod 架构。
  • 自动化它。 将脚本添加到您的项目中,以便在上游 API 发生更改时重新生成类型。
  • 无需帐户。 免费套餐允许每分钟 5 个请求,无需注册。
  • 适用于任何 JSON 源。 REST API、配置文件、数据库导出、Webhook 有效负载。

完整的 API 文档 封面 其他模式端点,包括 json-to-jsonschema 用于 JSON 模式输出。

FAQ

API 支持哪些 JSON 结构?
该 API 处理嵌套对象、数组、混合类型数组、空值和深度嵌套结构。 它推断每个值的正确 TypeScript 类型,包括存在 null 时的可选字段。
我需要 API 密钥吗?
否。允许匿名访问,每分钟 5 个请求,并具有基于 IP 的速率限制。 如需更高的容量,请在 botoi.com/api 上注册 API 密钥。
我可以生成 Zod 模式而不是 TypeScript 接口吗?
是的。 将相同的 JSON 正文发送到 POST https://api.botoi.com/v1/schema/json-to-zod,您将获得一个 Zod 架构字符串,您可以将其放入您的项目中。
API 如何处理混合类型的数组?
如果数组包含不同类型的值,API 会生成联合类型。 例如,包含字符串和数字的数组变为 (string | number)[]。
我可以在 CI 管道中使用它吗?
是的。 该 API 是标准 HTTP POST 端点。 从任何 shell 脚本、GitHub Action 或构建步骤调用它,以使类型定义与上游 API 响应保持同步。

开始使用 botoi 构建

150+ 个 API 端点,涵盖查询、文本处理、图片生成和开发者工具。免费套餐,无需信用卡。