使用openapi-typescript时,函数为何无法正确推导类型?
解决openapi-typescript生成类型后get函数返回值类型推导失败的问题
我通过openapi-typescript从Swagger服务生成了完整的类型定义,接着创建了仅包含GET方法路径的GetUrls类型。写好get函数后,URL的自动补全正常工作,但返回值类型无法正确推导;只有手动指定URL索引时,类型推导才会正常生效。
现有代码:
import { paths } from '../types/swagger.js' // 省略FilterPaths的实现代码 type GetPaths = FilterPaths<paths, 'get'> type GetUrls = keyof GetPaths & string // 省略Params类型定义 const get = async (url: GetUrls, params: Params) => { let path = '' for (let param in params) { path = url.replace('{' + param + '}', params[param]) } type Schema = GetPaths[typeof url]['get']['responses']['200']['content']['*/*'] return (await axios.get<Schema>(path)).data } get('/api/user/{id}', { id: '123' }).then(data => console.log(data))
手动指定索引时类型推导正常:
type Schema = GetPaths['/api/user/{id}']['get']['responses']['200']['content']['*/*']
解决方案
问题出在typeof url的类型是GetUrls联合类型,导致Schema变成了所有GET接口返回类型的集合,而非当前调用时传入的具体URL对应的类型。要解决这个问题,需要把get函数改成泛型函数,让TypeScript在调用时捕获具体的URL类型:
修改后的代码
import { paths } from '../types/swagger.js' // 实现FilterPaths工具类型(过滤出指定请求方法的路径) type FilterPaths<T, Method extends string> = { [K in keyof T]: Method extends keyof T[K] ? T[K] : never } type GetPaths = FilterPaths<paths, 'get'> type GetUrls = keyof GetPaths & string // 自动推导对应URL的路径参数类型 type PathParams<Url extends GetUrls> = GetPaths[Url]['get']['parameters']['path'] extends Record<string, infer ParamDef> ? { [K in keyof ParamDef]: ParamDef[K]['schema']['type'] } : {} const get = async <Url extends GetUrls>(url: Url, params: PathParams<Url>) => { let path = url // 替换路径参数 for (const param in params) { path = path.replace(`{${param}}`, params[param]) } // 精准获取当前URL对应的返回类型 type Schema = GetPaths[Url]['get']['responses']['200']['content']['*/*']['schema'] return (await axios.get<Schema>(path)).data } // 调用示例:此时data的类型会自动推导为/api/user/{id}接口的200返回类型 get('/api/user/{id}', { id: '123' }).then(data => { console.log(data) })
关键说明
- 泛型约束URL类型:通过
<Url extends GetUrls>将url参数的类型锁定为调用时传入的具体路径,而非联合类型,这样TypeScript能精准定位到对应的接口定义。 - 自动推导路径参数:新增的
PathParams泛型类型会根据传入的URL自动生成所需的参数结构,既保证类型安全,又不用手动定义每个接口的参数类型。 - 精准获取返回类型:现在
Schema基于泛型Url获取对应的返回类型,不再是所有类型的联合,解决了返回值类型推导失败的问题。
注意事项
- 若你的openapi-typescript生成的类型结构中,媒体类型不是
*/*(比如常见的application/json),需要调整content后的键名。 - 如果部分接口没有200响应,可添加条件类型处理这种情况,避免类型报错。
内容的提问来源于stack exchange,提问作者CNK
相关产品推荐
相关产品推荐

