ZeroTool Workbench

JSON 转 TypeScript 生成器

从任意 JSON 生成 TypeScript interface 声明。支持嵌套对象、数组、联合类型和可选属性,纯浏览器运行,免费在线工具。

100% 浏览器端运行 数据不离开你的设备 免费 · 无需注册
JSON 输入
TypeScript 输出

使用方法

  1. 将 JSON 粘贴或输入到左侧面板,工具会实时验证并高亮错误。
  2. 可选:设置 Root interface name(默认:RootObject)。
  3. 勾选 Make properties optional 可将所有字段标记为 ? 可选。
  4. 勾选 Use type instead of interface 可将输出关键字改为 type。
  5. 点击 Generate TypeScript 生成接口定义。
  6. 点击 Copy 将输出复制到剪贴板。

类型推断规则

  • null → 可选的 null(field?: null)
  • 字符串 → string
  • 数字 → number
  • 布尔值 → boolean
  • 空数组 → unknown[]
  • 对象数组 → 合并接口 + ItemName[]
  • 混合类型数组 → 联合类型,如 (string | number)[]
  • 嵌套对象 → 独立具名接口

示例

输入以下 JSON:

{"user": {"name": "Alice", "age": 30}, "tags": ["admin", "user"]}

工具生成:

interface RootObject {
  user: User;
  tags: string[];
}

interface User {
  name: string;
  age: number;
}

示例:API 响应

{
  "user": {
    "id": 42,
    "name": "Alice",
    "email": "[email protected]",
    "roles": ["admin", "editor"],
    "preferences": { "theme": "dark", "notifications": true },
    "lastLogin": null
  },
  "pagination": { "page": 1, "perPage": 20, "total": 143 }
}

生成:

interface RootObject {
  user: User;
  pagination: Pagination;
}

interface User {
  id: number;
  name: string;
  email: string;
  roles: string[];
  preferences: Preferences;
  lastLogin?: null;
}

interface Preferences {
  theme: string;
  notifications: boolean;
}

interface Pagination {
  page: number;
  perPage: number;
  total: number;
}

根接口排在最前,嵌套接口按出现顺序跟在后面。null 值会被写成类型 null 并标为可选,因为一个样本看不出字段有值时是什么类型。对照 API 文档后,改成 lastLogin: string | null 之类的写法。

示例:数组元素结构不同

{
  "items": [
    { "id": 1, "name": "a", "tags": [] },
    { "id": 2, "price": 9.5, "tags": ["x", 1] }
  ],
  "messages": [
    { "type": "text", "content": "hi" },
    { "type": "image", "url": "/a.png" }
  ]
}

生成:

interface RootObject {
  items: ItemsItem[];
  messages: MessagesItem[];
}

interface ItemsItem {
  id: number;
  name?: string;
  tags: (unknown[] | (string | number)[]);
  price?: number;
}

interface MessagesItem {
  type: string;
  content?: string;
  url?: string;
}

数组中的所有对象会合并:只在部分元素里出现的键加 ?。messages 实际上是按 type 区分的两种结构,合并后的接口会接受「text 消息带 url」这类无效组合,建议改写成可辨识联合类型(TypeScript 手册:Narrowing):

type Message =
  | { type: "text"; content: string }
  | { type: "image"; url: string };

示例:两个对象用了同一个键名

{
  "order": { "id": "A-1001", "meta": { "createdBy": "alice", "source": "web" } },
  "payment": { "status": "paid", "meta": { "provider": "stripe", "fee": 0.3 } }
}

生成

interface RootObject {
  order: Order;
  payment: Payment;
}

interface Order {
  id: string;
  meta: Meta;
}

interface Meta {
  createdBy: string;
  source: string;
}

interface Payment {
  status: string;
  meta: PaymentMeta;
}

interface PaymentMeta {
  provider: string;
  fee: number;
}

order.meta 得到名称 Meta。payment.meta 字段不同,所以单独生成一个接口,名称前加上父级:PaymentMeta。若它的字段与 order.meta 相同,两者共用 Meta。把两者合并成一个所有字段都可选的 Meta,会接受两个接口都不会返回的对象,所以每种结构各有自己的类型。名称仍被占用时加数字(Meta2)。即使嵌套键与根名称相同,根接口也保留你填写的名称。

需要手动调整的地方

  • null 字段:把 ?: null 改成真实类型加 | null。
  • 空数组:[] 生成 unknown[],需要补上元素类型。
  • 日期:ISO 8601 字符串和 Unix 时间戳分别保持 string、number。
  • 不是合法标识符的键(user-name、2fa)会加引号输出,这在 TypeScript 中是合法的。
  • PaymentMeta、Meta2 这类名称由 JSON 键名生成,可按业务含义改名。
  • 键名无法生成合法类型名时(2fa、空键名),接口名加前缀 T(T2fa);属性本身仍用带引号的原键名。

限制

  • 输入必须是合法 JSON(不能有注释或末尾逗号),报错信息会给出位置。
  • 类型只来自你粘贴的样本。样本里是字符串、线上有时是数字的字段,仍会是 string。
  • 勾选使用 type 替代 interface 后,每个声明写成 type Name = { ... };状态栏仍显示「接口」。

FAQ

这个工具生成什么?

它从 JSON 对象生成 TypeScript interface(或 type alias)声明。每个嵌套对象都会被提取为独立的具名接口;数组中的混合类型会生成联合类型。

嵌套对象如何处理?

每个嵌套对象字段会被提取为单独的接口,命名方式为字段名的 PascalCase。例如字段 'address' 对应 'Address' 接口,父接口引用该名称。

对象数组如何处理?

如果数组包含多个对象,所有对象的字段会合并为一个 item 接口。仅部分对象中存在的字段会被标记为可选。

'Make properties optional' 选项有什么用?

勾选后,所有生成接口的每个属性都会加上 '?' 后缀,变为可选。适合期望接收不完整数据或需要宽松类型定义的场景。

interface 和 type 有什么区别?

两者都可以描述对象结构。'interface' 支持声明合并,是对象类型的惯用写法;'type' 更灵活,还可以表示基本类型、联合类型和元组。勾选 'Use type instead of interface' 可切换输出关键字。

数据会发送到服务器吗?

不会。整个类型推断引擎完全在浏览器中运行,数据不会离开你的设备。