ToolPal
带有蓝色和橙色语法高亮的深色屏幕上的TypeScript代码

停止手写TypeScript接口:使用JSON生成器代替

📷 Roman Synkevych / Pexels

停止手写TypeScript接口:使用JSON生成器代替

从JSON有效载荷手动编写TypeScript接口既繁琐又容易出错。以下是如何自动化它以及需要注意的事项。

D作者: Daniel Park2026年4月7日2分钟阅读

如果你曾经花二十分钟从刚从API收到的JSON有效载荷手写TypeScript接口,你已经知道这是那些看起来重要但几乎完全是机械性的任务之一。你没有在思考,只是在复制字段名并推断类型。这是机器应该做的工作。

然而,许多开发者仍然手动做这件事。本指南介绍为什么停止这样做很值得,JSON to TypeScript生成器实际上生成什么,以及——更重要的是——它不能做什么,这样你就知道该在哪里接手。

TypeScript接口为什么真的很重要

在了解工具之前,值得明确从类型化接口中得到的东西,不仅仅是"捕获错误"。

IDE自动补全是被低估的一个。 当你的API响应被类型化时,你的编辑器确切知道哪些字段存在以及嵌套对象的形状。你不再需要猜测是user.profilePicture还是user.profile_picture还是user.avatar

重构变得更安全。 如果后端团队将字段从userId重命名为user_id,代码库中所有引用旧名称的地方在编译时就会中断——而不是在用户遇到错误后才发现。

不会过时的文档。 一个命名良好的接口通常比书面文档更有用。

手动过程与使用生成器

对于中等复杂度的API响应,手写类型是这样的:

{
  "user": {
    "id": 1042,
    "email": "alice@example.com",
    "name": "Alice Nguyen",
    "roles": ["admin", "editor"],
    "profile": {
      "bio": "Frontend developer based in Berlin.",
      "avatarUrl": "https://cdn.example.com/avatars/1042.png",
      "joinedAt": "2023-06-15T08:30:00Z"
    },
    "settings": {
      "theme": "dark",
      "notifications": {
        "email": true,
        "push": false
      }
    }
  },
  "meta": {
    "requestId": "abc-123",
    "timestamp": 1712486400
  }
}

将同样的JSON粘贴到JSON to TypeScript工具中,不到一秒就得到这个:

export interface Root {
  user: User;
  meta: Meta;
}

export interface User {
  id: number;
  email: string;
  name: string;
  roles: string[];
  profile: Profile;
  settings: Settings;
}

export interface Profile {
  bio: string;
  avatarUrl: string;
  joinedAt: string;
}

export interface Settings {
  theme: string;
  notifications: Notifications;
}

export interface Notifications {
  email: boolean;
  push: boolean;
}

export interface Meta {
  requestId: string;
  timestamp: number;
}

你所需要做的就是将Root重命名为像UserResponse这样有意义的东西。

真实世界的使用案例

API响应类型化

这是主要使用案例。你在与第三方API集成——支付处理器、CRM、天气服务——需要返回内容的类型。

配置文件

如果你的应用在运行时读取JSON配置文件,你需要一个匹配的TypeScript接口:

// config.interface.ts(从config.json生成)
export interface AppConfig {
  database: Database;
  redis: Redis;
  featureFlags: FeatureFlags;
}

export interface Database {
  host: string;
  port: number;
  name: string;
  ssl: boolean;
}

测试数据模拟

编写测试时,你经常需要类型化的模拟对象。从真实数据生成接口,然后根据它创建你的类型化模拟。TypeScript会告诉你模拟是否缺少必需字段。

处理棘手情况

Null值

JSON允许将null作为值,生成器会将这些字段类型化为null。但实际上,null字段通常意味着字段是可选的:

interface User {
  middleName: string | null;
}

日期

JSON没有原生的Date类型。"2023-06-15T08:30:00Z"就JSON而言是一个string,生成器将其类型化为string。一些团队创建类型别名:

type ISODateString = string;

可辨识联合

有时API根据typestatus字段返回不同的形状:

type ApiResult = SuccessResult | ErrorResult;

interface SuccessResult {
  type: "success";
  data: OrderData;
}

interface ErrorResult {
  type: "error";
  code: string;
  message: string;
}

生成类型的最佳实践

为根接口命名有意义的名称

生成器会将其命名为Root或通用名称。提交前始终重命名。UserProfileResponseCheckoutSessionPayloadProductListItem——使类型可查找且自解释的名称。

将类型保存在专用文件中

src/
  types/
    api/
      user.types.ts
      order.types.ts
    config.types.ts

使用Zod进行运行时验证

TypeScript类型在运行时被擦除——它们不保护你免受API实际返回意外数据的影响。如果需要运行时保证,考虑Zod

import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  email: z.string().email(),
  name: z.string(),
});

type User = z.infer<typeof UserSchema>;

生成器无法为你做的事情

它不知道你的业务逻辑。 类型化为number的字段在实际中可能只会是正整数。

它从快照工作。 生成的类型反映一个数据样本。真实的API会演进。

它无法区分必需和可选。 样本中的每个字段都被视为必需的。

它将所有字符串视为字符串。 只包含"pending""active""cancelled"status字段将被类型化为string,而不是更精确的联合类型。

这些不是避免使用工具的理由——它们是将输出视为草稿而非成品的理由。生成器处理80%的繁琐工作,你处理需要理解数据实际语义的20%。

综合运用

大多数项目有意义的工作流:

  1. 从API、配置或其他来源获取真实(或代表性)的JSON样本
  2. 粘贴到JSON to TypeScript生成器
  3. Root重命名为有意义的名称
  4. 将输出复制到适当的*.types.ts文件
  5. 检查每个字段:用?标记可选字段,在需要的地方添加| null,将适当的字面量字符串转换为联合类型
  6. 如果源JSON被压缩难以阅读,先使用JSON格式化工具,然后生成类型
  7. 如果同时维护YAML配置,JSON to YAML转换器可以帮助保持同步

目标是拥有准确、命名和组织好的TypeScript类型,而不在纯粹的机械转录上花时间。生成器做机械部分,你带来数据实际含义的背景知识。

手写的类型并不本质上更好——只是更慢且更容易出现拼写错误。使用工具,审查输出,把时间花在真正需要人类参与的部分。

常见问题

D

关于作者

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

了解更多

分享文章

XLinkedIn

相关文章