为已有的 JSON 响应手写 TypeScript 类型是重复性的工作,而且第一次 就微妙地写错很容易,特别是当字段是可选的或值嵌套了三层深的时候。
使用 JSON 到 TypeScript 生成器
粘贴文档,或数组中的多条记录,命名根类型,选择接口或类型别名, 然后点击生成类型。类型推断与本网站上的 Schema 生成器 共享,因此两个页面对你的文档实际包含什么达成一致,只是在如何书写 答案上有所不同。
给定
[
{"user": {"name": "a"}, "tags": [], "meta": {}},
{"user": {"name": "b"}, "tags": ["x"], "meta": {}, "extra": true}
]
输出是:
export interface RootItem {
user: User
tags: string[]
meta: Record<string, unknown>
extra?: boolean
}
export interface User {
name: string
}
export type Root = RootItem[]
为什么嵌套对象获得自己的命名类型
三层深的内联类型不可读,文件中的其他内容也无法引用它。名称来自
保存对象的键,在数组内被单数化(Root 的 RootItem),重复的名称
会附加一个数字,以便输出始终能编译而不产生冲突。
可选标记实际承诺什么
extra?: boolean 意味着该键在你的样本中至少一条记录里缺失,
与 Schema 生成器用于 required 的规则完全相同。这并不意味着该
字段在你的整个 API 中保证可选,只是你的样本无法证明它总是存在。
将该标记视为来自你的数据的证据,而非来自源系统的保证。
空值
空对象变成 Record<string, unknown> 而非空接口,因为空接口接受
任何东西且对形状说不出有用的信息。空数组变成 unknown[],因为
里面没有任何东西可以推断元素类型,凭空发明一个就是伪装成事实的
猜测。
为什么每个数字都只是 number
TypeScript 没有单独的整数类型,因此在你的样本中始终是整数的字段
仍然类型为 number,与包含小数的字段相同。这反映了 TypeScript
自身建模数字的方式,因此生成的类型编译后与手写类型的行为完全一致。