JSON → TypeScript 转换器,免费

粘贴 JSON,立即获得 TypeScript 接口。

没有数据离开您的设备

使用方法

  1. 将您的 JSON(对象或数组)粘贴到左侧面板。
  2. 点击转换· TypeScript 接口会出现在右侧。
  3. 根据需要调整根名称并启用选项。
  4. 点击复制输出以复制生成的代码。

常见问题

支持嵌套对象吗?

支持。每个嵌套对象都会获得自己的命名接口。数组元素也会被分析以确定元素类型。

混合类型的数组会怎样处理?

如果数组包含不同类型的元素,转换器会使用联合类型(例如 string | number)。

支持根节点为 JSON 数组吗?

支持。如果根值是数组,转换器会分析其元素并生成合适的接口,以及数组的类型别名。

转换器的实际工作原理

它解析您的JSON,遍历每个值,并生成一组描述该形状的TypeScript interface 声明。嵌套对象各自获得一个命名接口,名称从父属性键以PascalCase派生(user 字段变为 User 接口)。当两个嵌套对象在名称上冲突时,第二个获得数字后缀(UserUser2)。在根级别,数组变为 type Root = RootItem[]; 别名加上 RootItem 接口;对象变为单一 Root 接口(或您在「根名称」字段中填写的名称)。

示例输入与输出:

// Input
{
  "id": 42,
  "name": "Ada",
  "active": true,
  "tags": ["admin", "billing"],
  "profile": { "bio": "Programmer", "link": null }
}

// Output
export interface Root {
  id: number;
  name: string;
  active: boolean;
  tags: string[];
  profile: Profile;
}

export interface Profile {
  bio: string;
  link: unknown;
}

JSON → TypeScript 类型映射

JSON值生成的TS类型
"hello"string
423.14number(TS没有单独的整数类型)
true / falseboolean
nullunknown(转换器无法判断该字段在此样本中是可空还是缺失)
[]unknown[]
[1, 2, 3]number[]
[1, "x"](number | string)[]
{ "a": 1 }命名的 interface

对于根级别的对象数组,转换器将所有条目的键合并为一个代表性接口。当条目形状相同时这是合理的近似,但当形状确实存在差异时(例如异构事件数组)会丢失信息。对于这种情况,需要在生成后手动编写判别联合类型。

为什么对象用 interface,根数组用 type

TypeScript官方手册给出了一个简明启发原则:「如果需要启发式规则,请使用 interface,直到需要使用 type 的功能为止。」两者均为结构化类型,均可描述对象形状,但对于对象形状,interface 更优,因为它支持声明合并(重新打开接口添加字段)、与 extends 配合清晰,并在编译器错误中以名称形式显示。当需要原始类型的联合、多类型的交叉或为非对象内容命名时,type 别名是必要的,这就是为什么根级别数组使用 type Root = RootItem[]; 别名而非接口。

命名说明:转换器使用PascalCase,不带遗留的 I 前缀(使用 User 而非 IUser)。现代TS风格指南(Google、微软、React社区)几乎普遍去掉了该前缀。属性名与JSON键完全匹配(JSON使用camelCase则用camelCase,使用snake_case则用snake_case)。不是有效JS标识符的键(含连字符、空格或以数字开头的键)会被加引号:"foo-bar": string;

本工具的局限性(坦率说明)

单个JSON示例携带的信息比真实schema少,因此仅从输入无法检测到一些理想情况下应能检测到的内容:

适用场景

代码优先 vs 模式优先 vs 直接推断(本工具的定位)

从运行时数据获取TypeScript类型的三种常见工作流:

正确的选择取决于您的关注点主要是静态类型检查(本工具很适合)还是同时需要运行时安全(请使用Zod / Effect Schema)。

常见错误

  1. 将生成的类型视为完成的规范。它们只是70%完成的起点。为可选字段添加 ?,在真正可空的地方添加 | null,在适用的地方添加字符串字面量联合。
  2. 从单个示例生成,而API存在变体。一个有时包含 email 有时不包含的用户对象,将生成结果中该字段被视为「必填项」。请在多个示例上运行并对结果取联合,或手动编辑。
  3. 自动将所有内容标记为 readonly对不可变数据流有用,但对您要修改的状态对象不适用。请谨慎使用 readonly 开关。
  4. 相信大整数ID的精度。JavaScript的 number 上限为253−1。对于64位ID,请以字符串传输并类型化为 string
  5. 混淆 interfacetype不同的工具,各有权衡。TypeScript手册的启发原则是「除非需要只有type才具备的功能,否则使用interface」,这正是本工具所遵循的。
  6. 将机密JSON粘贴到服务器端转换器。真实的API响应通常包含客户数据、凭证、内部ID。仅在浏览器中转换(本工具)可确保数据留在您的设备上。

常见问题解答

为什么我的所有字段都被标记为必填?

因为单个JSON示例无法告诉转换器哪些字段在真实API中有时会缺失。示例中出现的每个键都变为必填项。如果您知道某个字段是可选的,请手动添加尾部 ?email?: string;。要进行多示例的可选性检测,更高级的 quicktype CLI原生支持此功能。

为什么我的null字段被类型化为 unknown

因为转换器无法从单个null中判断该字段是否始终可空(string | null),还是在此样本中恰好为null(string)。unknown 是保守的默认值;TypeScript会强制您在使用值之前缩小类型,这比 any 更安全。了解API意图后,手动编辑为 string | null

我应该使用 interface 还是 type

TypeScript官方手册的启发原则:使用 interface,直到需要只有 type 才提供的功能,主要是联合类型、交叉类型或为原始类型命名。本转换器遵循该规则:每个对象形状使用 interface,根数组别名使用 type。部分风格指南建议默认使用 type(Matt Pocock曾公开论证过),但传统默认是对象使用interface。

我的JSON会被上传到任何地方吗?

不会。转换是一个自包含的JavaScript IIFE,通过 JSON.parse 解析您的JSON,遍历值,并将TypeScript输出写入文本区域。没有fetch请求,没有携带JSON内容的分析调用,没有服务器。这很重要,因为真实的API响应通常包含客户数据、内部ID或凭证,您不希望这些流经第三方。

关于JSDoc、Zod或运行时验证呢?

本工具仅生成编译时TypeScript类型:无运行时验证器(无Zod / Yup / Effect Schema),无JSDoc注释。如果需要兼具静态类型的运行时验证,请在Zod中编写模式并使用Zod的 z.infer<typeof Schema> 来派生类型。如果您有JSON Schema并希望同时进行运行时验证和TS类型生成,json-schema-to-typescript + AJV是常用的组合。

为什么接口名称没有 I 前缀?

因为大多数现代TypeScript风格指南都去掉了它。Google的TypeScript风格指南明确建议反对使用;React社区已统一使用无前缀的PascalCase。遗留的 IUser 约定来自早期TypeScript中C#/Java的影响;当前实践是直接使用 User

相关工具

免费在线 JSON 格式化器和验证器 JSON → Go struct 转换器,免费 JSON Schema 生成器,免费