Schema 转 TypeScript 把一份 JSON Schema 转成等价的 TypeScript 类型定义,让前端代码从编辑期就能享受字段补全、类型检查、重构安全。所有转换在浏览器本地完成,不联网。
| JSON Schema | TypeScript |
|---|---|
type: "string" | string |
type: "integer" / "number" | number |
type: "boolean" | boolean |
type: "null" | null |
type: "array", items: T | T[] |
prefixItems: [A, B](2020-12) | [A, B] |
type: "object", properties + required | interface |
enum: [...] | 字面量联合 "a" | "b" |
const: X | 字面量 X |
anyOf / oneOf | 联合 A | B |
allOf | 交叉 A & B |
$ref → #/$defs/X | 引用类型 X |
additionalProperties: T | [k: string]: T 索引签名 |
字段按 required 列表决定必选 / 可选;对象转 interface、其它转 type;definitions / $defs 提升为顶层类型,命名沿用 Schema 里的 key。description 字段会生成对应 TSDoc 注释(/** ... */)。
integer 和 number 都映射为 TS 的 number(语言限制)pattern / minLength / maximum 等运行时约束无法在类型系统表达,需要配合运行时校验器(如 Schema 校验器)$ref URL(如跨文件、跨域)if / then / else、dependentSchemas)转为 unknowninterface 还是 type?默认对象类型出 interface(export interface User { id: number; name: string }),其它(enum / union / primitive / tuple)出 type(比如 export type Role = 'admin' | 'user')。$defs 和 definitions 里声明的子 Schema 会被提到顶层作为独立类型,根 Schema 用 根类型名(默认 Root,可改成 User 等)。
anyOf / oneOf / allOf 怎么映射?anyOf 和 oneOf 都转成 联合类型(A | B)——TypeScript 结构类型系统没有"严格互斥"的直接表达,工具按联合处理。allOf 转成 交叉类型(A & B)。如果需要严格互斥语义,请在生成的 TS 基础上手动加 discriminated union(按 type 字段区分)。
$ref 会被展开还是保留引用?保留引用——$ref: "#/definitions/Address" 转成 TS 里的 Address 类型引用,前提是 definitions / $defs 里确实有这个名字。工具不会联网解析外部 $ref(如 https://...),遇到外部引用会转为 unknown。同文件内的循环引用(A 引 B、B 引 A)也能正确处理。
integer 变成了 number?TypeScript 原生没有整数类型——number 统一表示所有数值,包括整数和浮点数。Schema 里的 integer 约束是运行时规则(由校验器保证),编译期通过 TS 类型系统无法表达。想要严格区分可以用 integer 分支类型,但会让类型接入成本飙升,工具默认不生成。
enum 会生成 TS enum 吗?不会,生成联合字面量类型(type Role = "admin" | "user" | "guest")。原因:TS enum 会在编译后产生运行时对象,侵入性高;联合字面量类型则纯在编译期,轻量且互操作性更好。这也是 json-schema-to-typescript 等主流库的默认做法。
required 以外的字段会怎样?标记为可选(字段名后加 ?)并允许 undefined。Schema 里 required: ["id", "name"] 时,email、role 这些没列入 required 的字段在 TS 里变成 email?: string。这与 JSON Schema 的默认语义一致:没列入 required 就是可以缺省。