typeof 配合 as const 是最快生成静态 json 响应接口的方式,需确保样例结构稳定且含 as const 锁定字面量精度;infer 可从泛型响应中提取 data 类型;keyof + record 适用于键已知的枚举类配置。

直接用 typeof + as const 推出最简接口,但仅限静态响应样例
如果你手头有后端返回的 JSON 样例(比如 Swagger 示例、Postman 响应、Mock 数据),且结构稳定、不含动态字段,typeof 配合 as const 是最快生成接口的方式——它不依赖网络或运行时,纯编译期推断。
常见错误是直接 typeof 一个普通对象字面量,结果推成 string 或 number 字面量类型,丢失结构信息。必须加 as const 锁定所有层级的可读性与字面量精度:
const mockUser = {
id: 123,
name: "Alice",
email: "a@example.com",
tags: ["admin", "vip"] as const, // ← 关键:让 tags 推为 readonly ["admin", "vip"]
profile: { avatar: "https://...", bio: "dev" } as const
} as const;
type User = typeof mockUser;
// 推出:{ readonly id: 123; readonly name: "Alice"; ... }
- 只适用于小而确定的响应片段;嵌套过深或含
Date/Buffer等无法序列化的值会失败 -
as const后所有属性自动变为readonly,若需可变字段,得手动覆盖:如type MutableUser = { -readonly id: number } & User - 字段名含空格、中划线等非法标识符时,
typeof仍能推,但后续使用需用方括号访问,IDE 补全会弱化
infer 在泛型函数中提取 Axios/Fetch 响应的 data 类型
你不需要每次请求都写 AxiosResponse<user></user>。用条件类型 + infer 可从泛型参数中“抓出”实际数据类型,让调用侧保持干净。
以 Axios 为例,假设统一响应结构是 { code: number; message: string; data: T },你可以这样封装:
type ApiResponse<t> = { code: number; message: string; data: T };
// 提取 data 的类型
type DataOf<t> = T extends ApiResponse<infer u> ? U : never;
// 使用
const userRes = await axios.get<apiresponse>>("/api/user/1");
type UserType = DataOf<typeof userres.data>; // ← 此时就是 User,不是 ApiResponse<user></user></typeof></apiresponse></infer></t></t>
- 别在
axios.get调用时直接写<user></user>,那是错的——Axios 默认推AxiosResponse<any></any>,泛型参数应填完整响应体类型 - 如果后端字段名不固定(比如分页接口的
list/items字段名随业务变),infer就无能为力,必须靠接口定义或运行时校验 - Fetch 场景下同理,但注意
response.json()返回Promise<any></any>,必须显式 cast 或用as const样例辅助推断
用 keyof + Record 动态构造响应字段的联合类型
当 API 返回字段是枚举式字符串键(如状态码映射、配置项 key),且值类型一致,没必要为每个字段单独定义接口。用 keyof 和 Record 可自动生成强类型字典。
例如后端返回一个状态码描述表:
const statusMap = {
"200": "OK",
"400": "Bad Request",
"404": "Not Found",
"500": "Internal Error"
} as const;
type StatusCode = keyof typeof statusMap; // ← "200" | "400" | "404" | "500"
type StatusText = Record<statuscode string>; // ← { "200": string; "400": string; ... }
</statuscode>
- 这种模式适合配置类、枚举类、多语言文案等“键已知、值结构简单”的场景
- 如果键来自变量(比如
Object.keys(obj)),keyof会退化为string,失去精确性;必须用as const固定键集合 - 和
in操作符配合时,TypeScript 能做控制流分析,但 IDE 对动态键的跳转支持较弱
真正难的是处理运行时不可知的嵌套结构
上面所有技巧都建立在一个前提上:响应结构在编译期可被 TypeScript 触达。一旦涉及以下情况,自动化推断就失效,必须人工介入:
- 后端返回字段名由参数动态拼接(如
fields=user.name,user.email,order.id) - 响应中存在
any或unknown字段(比如富文本内容、第三方插件扩展字段) - 同一接口在不同环境返回不同结构(开发环境 mock 返回简化版,生产环境返回全量字段)
这时候,interface 不是冗余,而是必要契约。泛型可以帮你减少重复,但不能替代对业务语义的理解。最常被忽略的一点是:**类型推断再智能,也无法代替接口文档里对字段含义、空值逻辑、枚举边界值的说明**——那些永远得人来写。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











