直接用 typeof + as const 推静态样例最省事,但嵌套深、字段动态、含 Date 或 Buffer 时失效;必须用条件类型 + infer 解出 data 类型,否则接口与运行时脱节。

直接用 typeof + as const 推静态样例最省事,但遇到嵌套深、字段动态、含 Date 或 Buffer 的真实响应,它就失效了;这时候必须靠条件类型 + infer 从泛型中“捞”出 data 类型,否则接口定义会和运行时脱节。
用 DataOf<t></t> 从统一响应结构里提取实际数据类型
多数项目后端返回结构固定:{ code: number; message: string; data: T }。手动写 AxiosResponse<apiresponse>></apiresponse> 不仅啰嗦,还容易漏掉泛型层级。
-
DataOf<t></t>是个条件类型,只在T确实是ApiResponse<u></u>形式时才解出U,否则回退到never - 别在
axios.get()调用时传<user></user>——那是错的,get的泛型参数应填完整响应体类型,比如<apiresponse>></apiresponse> - 如果后端分页字段名不固定(比如有时叫
list,有时叫items),infer没法自动识别,得靠额外接口定义或运行时校验
type ApiResponse<T> = { code: number; message: string; data: T };
type DataOf<T> = T extends ApiResponse<infer U> ? U : never;
// 正确用法
const res = await axios.get<ApiResponse<User>>('/api/user');
type UserType = DataOf<typeof res.data>; // → User
处理字段名不固定或含非法标识符的响应
当 API 返回字段含空格、中划线(如 "user-id")、点号等 JS 非法属性名时,typeof 仍能推导,但后续访问必须用方括号语法,且 IDE 补全会变弱。
使用 Scrapfly SDK(scrapfly-sdk)在 TypeScript 或 JavaScript 中进行网页抓取,用于用户请求抓取 URL、绕过反爬虫防护、渲染页面等场景。
-
as const可保留字面量精度,但无法解决属性名合法性问题;字段名本身会被推为字符串字面量类型 - 若需强类型访问,建议用
Record<string unknown></string>+ 运行时 key 校验,或用keyof+Record显式枚举合法键 - 避免在类型层面硬编码非法字段名,容易导致类型与运行时不一致
嵌套 Promise 或异步响应的类型解包
调用 fetch().then(r => r.json()) 后得到的是 Promise<any></any>,直接 typeof 拿不到结构;需要先用条件类型把 Promise 层剥掉。
-
UnpackPromise<t></t>只解一层,DeepUnpack<t></t>支持递归解包(比如Promise<promise>></promise>) - 注意
response.json()返回的是Promise<any></any>,必须配合as Promise<apiresponse>></apiresponse>或类似断言才能触发infer - 如果后端返回值含
Date字符串(如"2026-05-10"),TypeScript 无法自动转成Date实例,得靠运行时解析或自定义序列化类型
type UnpackPromise<T> = T extends Promise<infer U> ? U : T; type DeepUnpack<T> = T extends Promise<infer U> ? DeepUnpack<U> : T; // 示例 type Raw = Promise<ApiResponse<User>>; type Unpacked = DeepUnpack<Raw>; // → ApiResponse<User>
真正难的不是写对 infer,而是确认后端响应结构是否稳定——字段增删、嵌套层级变化、空值策略调整,都会让基于样例或泛型推导的类型瞬间过期。与其花时间补类型,不如推动后端提供可验证的 OpenAPI Schema。

















