如何让OpenAPI Generator生成的TypeScript链式调用方法正确推导返回类型(避免Promise<any>)
嘿,这个问题我之前也踩过坑!OpenAPI Generator生成的TypeScript-Axios代码确实偶尔会出现链式调用时类型推导失效、返回Promise<any>的情况,拆分语句反而能正常推断成Promise<AxiosPromise<User>>,下面给你几个靠谱的解决思路:
一、先升级OpenAPI Generator到最新稳定版
旧版本的生成器可能存在类型推导的bug,这是最常见的原因。你可以先检查当前使用的镜像版本:
docker run --rm openapitools/openapi-generator-cli version
然后换成最新的稳定版镜像重新生成,比如用v7.6.0(替换成当前最新版即可):
docker run --rm -it --name openapi-gen -v "$(pwd)":/mnt/workdir -w /mnt/workdir openapitools/openapi-generator-cli:v7.6.0 generate -i petstore.yaml -g typescript-axios
很多时候升级后这个问题就自动解决了。
二、调整生成器的配置参数
TypeScript-Axios生成器有几个关键配置可以优化类型推导,你可以通过--additional-properties参数直接指定,或者用配置文件更清晰:
方式1:命令行直接加参数
docker run --rm -it --name openapi-gen -v "$(pwd)":/mnt/workdir -w /mnt/workdir openapitools/openapi-generator-cli generate -i petstore.yaml -g typescript-axios --additional-properties=supportsES6=true,typescriptThreePlus=true,useSingleRequestParameter=false
supportsES6=true:启用ES6特性,帮助TypeScript更好地推导类型typescriptThreePlus=true:针对TS3.0+版本优化类型生成useSingleRequestParameter=false:避免把参数合并成单个对象,可能影响类型推导
方式2:用配置文件(推荐)
在项目根目录创建openapi-generator-config.json:
{ "supportsES6": true, "typescriptThreePlus": true, "useSingleRequestParameter": false, "modelPropertyNaming": "camelCase" }
然后生成命令改成:
docker run --rm -it --name openapi-gen -v "$(pwd)":/mnt/workdir -w /mnt/workdir openapitools/openapi-generator-cli generate -i petstore.yaml -g typescript-axios -c openapi-generator-config.json
三、临时应急:手动补全类型(不推荐长期用)
如果暂时无法升级或调整配置,你可以给链式调用手动指定类型,或者在生成的API文件里添加类型别名:
// 手动指定返回类型 const userPromise: Promise<AxiosPromise<User>> = api.getUser().someChainMethod(); const user = await (await userPromise).data;
当然这只是临时方案,还是建议从生成器本身解决问题。
额外问题:让TypeScript识别await AxiosPromise<T>直接返回T
默认情况下,AxiosPromise<T>是Promise<AxiosResponse<T>>的别名,所以await后得到的是AxiosResponse<T>,需要取.data才能拿到T。如果你想让TypeScript直接识别await AxiosPromise<T>为T,可以这么做:
方法1:封装一个unwrap工具函数
import { AxiosPromise, AxiosResponse } from 'axios'; async function unwrapAxios<T>(promise: AxiosPromise<T>): Promise<T> { const response: AxiosResponse<T> = await promise; return response.data; } // 使用示例 const user: User = await unwrapAxios(api.getUser());
方法2:全局类型声明简化(可选)
你可以在项目的全局类型文件(比如src/types/axios.d.ts)里扩展Axios的类型,但注意这不会改变运行时行为,只是让TS类型推导更友好:
declare module 'axios' { export type UnwrappedAxiosPromise<T> = T extends AxiosPromise<infer U> ? U : T; } // 使用时可以用类型别名 const user: Axios.UnwrappedAxiosPromise<ReturnType<typeof api.getUser>> = await (await api.getUser()).data;
不过更推荐直接用.data或者上面的工具函数,因为这更符合Axios的原生设计。
备注:内容来源于stack exchange,提问作者grabantot

