@hey-api/openapi-ts 并不是一个简单的“替换”,而是一次面向复杂需求的“升级”。 它是一个功能更全面的现代化工具集,与专注生成类型的 openapi-typescript 定位不同。
🔎 核心差异一览
下面的表格可以清晰地展示这两个工具的核心区别:
| 维度 | @hey-api/openapi-ts | openapi-typescript |
|---|---|---|
| 定位 | 一站式 TypeScript 工具链,生成类型、客户端、SDK 等。 | 专注的 类型生成器,只生成 TypeScript 类型定义。 |
| 核心产出 | SDK 客户端 + 类型定义 + 校验器等。 | 纯类型定义文件 (.d.ts)。 |
| 生态集成 | 强,内置 20+ 插件,可集成 Fetch, Axios, TanStack Query 等。 | 弱,通常需要配合 openapi-fetch 等额外工具使用。 |
| 扩展性 | 高,通过插件系统灵活定制。 | 中,提供配置选项但扩展性有限。 |
| 运行时开销 | 有,会生成包含业务逻辑的代码。 | 零,产出的纯类型定义不会增加包体积。 |
| 社区与生态 | 活跃的新兴工具,被 Vercel, PayPal 等公司使用。 | 成熟,拥有更庞大的社区和丰富的文档。 |
| 适用项目 | 中大型、需要全链路类型安全和框架集成的项目。 | 任何规模、追求极简轻量的项目,或作为 @hey-api/openapi-ts 的“组件”使用。 |
| 前身 | 是 openapi-typescript-codegen 的活跃分支。 | 无。 |
🛠️ 不止这两个选择:聊聊其他替代方案
除了这两个,TypeScript 生态中还有其他优秀的工具:
-
Orval:功能强大,尤其擅长生成与 TanStack Query 等框架深度集成的 API Hooks,如果你的项目重度使用 React Query,它是一个非常值得考虑的选择。
-
Swagger Typescript API:老牌工具,能生成包含完整请求逻辑的 API 客户端代码,功能全面但学习曲线可能稍高。
-
vika-cli:新兴工具,最大特点是快(使用 Rust 编写),不仅能生成类型和客户端,还能生成 Zod 校验模式。
-
Kiota:微软官方出品,支持多语言,如果你的技术栈深度绑定微软生态,这是一个优势。
-
tRPC:如果你能同时控制前后端,并且都使用 TypeScript,tRPC 能提供端到端的、无需代码生成的极致类型安全体验。
🤔 所以,我该怎么选?
你的选择取决于项目的具体需求和优先级:
-
我只需要静态类型,追求极致轻量:
选openapi-typescript。它完美地做到了“一件事并把它做好”,没有任何运行时负担,适合任何需要 API 类型定义的项目。 -
我需要一套完整的解决方案,以提升团队效率:
选@hey-api/openapi-ts。特别是当你的项目需要与Fetch/Axios客户端、TanStack Query等框架深度集成时,它能为你生成所有胶水代码,极大提升开发效率。 -
我需要生成带有运行时校验的代码:
可以关注vika-cli这类能同时生成类型和 Zod 校验模式的新兴工具。 -
我追求端到端的极致类型安全,且能控制全栈:
可以考虑tRPC。它提供了一种不同于 REST 的范式,能让你的 API 调用从前端到后端完全类型安全。
💎 总结
总的来说,选择哪个工具,本质上取决于你对“类型安全”的需求层次。openapi-typescript 是解决“是什么类型”这一基础问题的利器。而 @hey-api/openapi-ts 及其同类工具,则是在此基础上,进一步解决“如何用”和“如何更好地集成”的问题。
希望这份对比能帮你找到最适合自己项目的工具~
但是openapi-typescript解决不了Java枚举和TypeScript枚举的问题呀
你说得非常对,这确实是 openapi-typescript 的一个核心痛点:它生成的 联合类型 (Union Type),无法直接对应 Java 后端的枚举,特别是在命名和 IDE 智能提示方面存在短板。
不过别担心,这个问题有不止一种解法。@hey-api/openapi-ts 不仅解决了问题,还提供了更灵活的选择。
🎯 你遇到的核心痛点:命名映射的缺失
openapi-typescript 默认生成的代码是纯静态的联合类型(如 type Status = 'APPROVED' | 'REJECTED')。这可以保证类型安全,但丢失了枚举的"常量名"。当后端 Java 枚举的字符串值(如 "Approved Request")包含空格等特殊字符时,openapi-typescript 在生成时会将其统一替换为下划线 _,这会破坏代码的可读性和映射关系。
💡 解法一:用 @hey-api/openapi-ts 和扩展字段生成 TS 枚举
@hey-api/openapi-ts 配合 OpenAPI 的 x-enum-varnames 扩展字段,是解决命名映射问题的最直接方案。
它的核心思路是: 在后端 OpenAPI 定义中,通过 x-enum-varnames 字段,明确告知生成器前端期望的 TypeScript 枚举键名。这样一来,就实现了前后端枚举的解耦。
具体步骤如下:
-
后端定义 (OpenAPI Spec):在 Schema 中定义枚举值和对应的 TS 键名。
yaml
UserRole: type: string enum: - admin_user - regular_user x-enum-varnames: - ADMIN # 告诉生成器,admin_user 对应 TS 枚举键名 ADMIN - USER # 告诉生成器,regular_user 对应 TS 枚举键名 USER -
配置
@hey-api/openapi-ts:在生成配置中,将enums.mode设置为typescript,让它生成真正的 TS 枚举而不是联合类型。javascript
export default { input: 'path/to/openapi.yaml', output: 'src/client', plugins: ['@hey-api/sdk'], enums: { mode: 'typescript' // 生成真正的 TypeScript 枚举 } }这项功能在
@hey-api/openapi-ts的较新版本中已得到支持。 -
前端使用 (Generated Code):最终生成的前端代码将是一个标准的 TS 枚举。
typescript
export enum UserRole { ADMIN = 'admin_user', USER = 'regular_user' }
⚙️ 解法二:用插件或直接生成常量枚举
如果不想在 OpenAPI 文件中添加扩展字段,或者想探索其他方式,可以尝试以下两种路径。
-
路径一:使用
openapi-typescript的生态插件
可以试试@openapi-typescript-infra/openapi-typescript-enum这个社区插件。它能作为openapi-typescript的一个替代命令运行,将原来生成的联合类型替换为真正的enum对象。 -
路径二:使用
@hey-api/openapi-ts生成常量枚举
@hey-api/openapi-ts也提供了灵活的配置。将enums.mode设置为typescript.const,就能生成一个as const断言的对象,这在某些场景下可能比enum更轻量,也更受现代 TS 风格的青睐。javascript
export default { // ...其他配置 enums: { mode: 'typescript.const' // 生成 as const 对象 } }根据你的项目风格,在
enum和as const之间做选择。
🤔 如何抉择:两种方案的对比
为了方便你决策,我把两种核心解法再对比一下:
| 对比维度 | 方案一:x-enum-varnames 映射 | 方案二:插件/常量枚举 |
|---|---|---|
| 灵活性 | 高,可在 OpenAPI 层精确控制命名,与后端 Java 枚举值完全解耦。 | 中,无法自定义命名,只能使用枚举的原始值作为键名。 |
| 集成成本 | 中,需要修改后端 OpenAPI 文件,且需生成工具支持(@hey-api/openapi-ts 等支持)。 | 低,前端即可完成配置,无需后端配合。 |
| 适用场景 | 对类型命名有严格要求,追求前后端枚举完美映射的大中型项目。 | 快速原型开发,或对前端枚举命名没有特殊要求的项目。 |
💎 总结
简单来说,你的问题归结为能否修改后端 OpenAPI 定义。
-
如果能修改,那么使用
@hey-api/openapi-ts+x-enum-varnames的方案是最彻底、最专业的解法。 -
如果不能修改,那么使用
@hey-api/openapi-ts的常量枚举模式或社区插件,是在现有约束下的最佳实践。
Vue3+Vite+TypeScript+axios的技术栈,最佳选择是哪个?
对于 Vue3 + Vite + TypeScript + Axios 这个技术栈,推荐的首选方案是 orval。
orval 凭借对 Axios 的深度集成和 Vue Query 的原生支持,几乎能开箱即用地满足你的所有技术栈需求。而 @hey-api/openapi-ts 虽然功能同样强大,但在这个特定组合下,需要更多配置才能达到同等的集成效果。
🛠️ 核心工具快速对比
为了让你更直观地了解,我准备了下面这个对比表格:
| 特性 | orval (首推) | @hey-api/openapi-ts | openapi-typescript |
|---|---|---|---|
| 定位 | 一站式API客户端生成器,开箱即用 | 模块化的代码生成工具链,高度可定制 | 轻量级类型生成器,只做一件事 |
| Axios 集成 | 原生支持,配置简单 | 支持,但需要额外安装 @hey-api/client-axios 插件 | 不涉及,仅生成类型,需自己用Axios请求 |
| Vue 集成 | 原生支持 vue-query,可直接生成 useQuery 等组合式函数 | 需额外配置 @tanstack/vue-query 插件 | 不涉及 |
| Vite 性能 | 标准Node.js工具,生成速度适中 | 标准Node.js工具,生成速度适中 | 极快,纯类型生成无运行时开销 |
| 枚举处理 | 支持生成真正的TS枚举,符合预期 | 支持,但需配合 x-enum-varnames 等额外配置 | 不支持,默认转为联合类型,处理不规范值可能出错 |
| 生态成熟度 | 成熟,社区活跃 | 新兴,增长迅速,已被Vercel、PayPal等采用 | 非常成熟,广泛应用 |
🏆 为什么 orval 是你的技术栈最佳选择?
对于你选择的 Vue3 + Vite + TypeScript + Axios 技术组合,orval 几乎是为它量身定做的:
-
与你技术栈的无缝集成:
orval原生支持axios,能直接生成你需要的请求代码。同时,它也能为vue-query生成对应的组合式函数(Composables),帮你轻松实现服务端状态管理,与 Vue 3 的生态完美契合。 -
出色的枚举处理:
orval能直接将 OpenAPI 中的枚举生成标准的 TypeScriptenum,彻底解决你之前遇到的枚举问题,无需任何额外配置。 -
配置简单,上手快:
orval的目标是开箱即用。你只需要一个简单的配置文件,就能直接生成完整的、类型安全的 API 客户端代码。
🥈 为什么不首选另外两个?
-
@hey-api/openapi-ts:它的理念更偏向于提供一个灵活的“工具集”而非“开箱即用”的方案。要让它完美适配你的技术栈,需要进行更多配置和组合。例如,你需要自行组合@hey-api/client-axios和@tanstack/vue-query等插件,这在一定程度上增加了上手成本。 -
openapi-typescript:它的定位非常专一,就是“生成类型”。它本身不会为你生成任何请求客户端代码,你需要自己编写 Axios 请求逻辑并手动引入它生成的类型。因此,它虽然零运行时开销,但无法提供像orval那样一站式的便利。它也更适合与其他工具如openapi-fetch搭配,而这又会引入新的学习成本。
🚀 快速上手指南:使用 orval
在你的 Vue3 + Vite 项目中集成 orval 非常简单,只需几步:
1. 安装
在项目根目录下,使用你喜欢的包管理器安装 orval:
bash
# 使用 pnpm pnpm add orval --save-dev # 或者使用 npm npm install orval --save-dev
2. 配置
在项目根目录创建 orval.config.ts 文件。这是一个基础配置示例,你可以根据项目需要调整:
typescript
import { defineConfig } from 'orval';
export default defineConfig({
'your-api': { // 一个自定义的配置名称
input: {
target: 'http://localhost:8080/api-docs/openapi.json', // 你的OpenAPI规范URL
},
output: {
mode: 'split', // 推荐使用 'split' 模式,将服务和模型分开生成
target: './src/api/client.ts', // 生成的客户端文件路径
schemas: './src/api/models', // 生成的TypeScript模型路径
client: 'axios', // 指定使用axios客户端
baseUrl: '/api', // 你的API基础路径
clean: true, // 生成前清理输出目录
},
hooks: {
afterAllFilesWrite: 'prettier --write', // 可选:生成后自动格式化代码
},
},
});
3. 生成
在 package.json 中添加一个脚本命令:
json
"scripts": {
"generate-api": "orval --config ./orval.config.ts"
}
然后运行以下命令,即可生成完整的 TypeScript API 客户端:
bash
pnpm run generate-api # 或者 npm run generate-api
4. 在 Vue 组件中使用
生成的客户端可以直接在 Vue 组件中导入并使用,享受完整的类型提示和检查。
typescript
// 在 your-component.vue 中
<script setup lang="ts">
import { useGetUsers } from '@/api/client'; // 自动生成的组合式函数
// 或者直接调用API函数
// import { usersControllerGetUsers } from '@/api/client';
// 使用 Vue Query 钩子
const { data, isLoading, error } = useGetUsers();
// 也可以直接调用API函数
// const fetchUsers = async () => {
// const response = await usersControllerGetUsers();
// console.log(response.data);
// };
</script>
Vue3+Vite+TypeScript+axios的技术栈,最佳选择是哪个?
orval 依然是你的技术栈下,能兼顾开发效率与代码质量的最佳选择。不过,技术生态一直在发展,除了 orval,现在还有几个非常值得关注的工具,它们各有侧重,能应对不同场景下的挑战。
📊 四大工具方案深度对比
下面是四个最主流方案的详细对比,可以帮助你更清晰地看到它们的差异:
| 特性维度 | 🏆 orval | ⚙️ @hey-api/openapi-ts | 🏗️ openapi-generator | 🎯 swagger-typescript-api |
|---|---|---|---|---|
| 核心理念 | 全链路、框架优先的客户端生成器,为现代前端框架深度优化 | 模块化、插件化的工具链,功能高度可定制 | 官方、全面的多语言代码生成器,企业级之选 | 轻量、直接的类型安全API生成器,简单高效 |
| Axios 集成 | 原生支持,client: 'axios' 配置即可生成完整的、可直接使用的请求代码。 | 需要插件,通过 @hey-api/client-axios 插件生成 Axios 客户端包装器。 | 官方支持,通过 -g typescript-axios 生成器直接生成 Axios 客户端代码。 | 原生支持,通过 --axios 参数即可生成 Axios 客户端代码。 |
| Vue 3 生态 | 深度集成,通过 client: 'vue-query' 直接生成 TanStack Query 的 Vue Composable 钩子。 | 中等集成,需自行安装并配置 @tanstack/vue-query 插件来生成相关代码。 | 基础集成,专注于生成标准Axios客户端,不包含特定框架的状态管理集成。 | 基础集成,专注于生成标准Axios客户端,需自行封装Vue Query逻辑。 |
| 生成类型风格 | 强类型 SDK,生成完整的、可直接调用的API客户端函数。 | 灵活 SDK,根据选择的插件生成SDK或类型。 | 标准 SDK,生成基于类的标准客户端SDK。 | 函数式 API,生成可直接调用的API请求函数。 |
| 配置复杂度 | 低,配置文件清晰,开箱即用。 | 中高,功能强大但需理解插件系统。 | 中,CLI参数或配置文件,但选项繁多。 | 极低,主要依靠CLI命令,配置简单。 |
| 项目规模 | 中大型,追求极致开发效率和框架集成的项目。 | 大中型,需要深度定制代码生成逻辑的项目。 | 企业级,需要多语言支持、成熟稳定的解决方案。 | 中小型,追求快速集成和轻量级解决方案的项目。 |
| 社区与维护 | 活跃,专为现代前端而生。 | 活跃,创新迅速,被知名公司采用。 | 非常成熟,OpenAPI官方工具,社区庞大。 | 活跃,专注TypeScript/JavaScript生态。 |
🚀 如何为你的项目精准选择?
了解了各方案的差异,你可以根据项目当前所处的阶段和未来的规划,做出最合适的决定。
🏆 首选方案:orval
如果你的团队追求高效的开发体验和完备的类型安全,orval 依然是综合体验的最佳选择。它能为你生成全链路的类型安全请求代码,并与 Vue 3 生态无缝集成。
-
极速上手:只需一个配置文件,即可从 OpenAPI 规范生成完整的、带有类型定义的 API 客户端,无需手动编写任何请求代码。
-
深度集成 Vue 3:它可以直接生成基于
TanStack Query(原Vue Query) 的 Composable 钩子,极大简化了在 Vue 3 组件中进行数据获取、缓存和更新的逻辑。 -
完美解决你的痛点:它能自动将 Java 后端的枚举生成为 TypeScript 的
enum,彻底解决类型不一致的问题。
⚙️ 新兴之选:@hey-api/openapi-ts
如果项目有定制代码生成逻辑的需求,例如需要生成特定格式的请求/响应拦截器,或者需要同时支持多种HTTP客户端(如同时生成Fetch和Axios客户端),@hey-api/openapi-ts 是非常强大的备选方案。
-
模块化与可扩展:其插件化架构允许你按需组合功能,例如,你可以通过安装
@hey-api/client-axios插件来生成 Axios 客户端,再组合其他插件来满足特定需求。 -
面向未来:作为较新的工具,它采用了更现代的设计思想,并已被 Vercel、PayPal 等公司采用,发展前景良好。
🏗️ 企业级之选:openapi-generator
对于大型企业级项目,稳定性和多语言支持是首要考量,那么 OpenAPI 官方出品的 openapi-generator 是最稳妥的选择。
-
官方血统,稳定可靠:作为 OpenAPI 官方工具,它支持几乎所有主流编程语言,并提供
typescript-axios生成器,可直接生成基于 Axios 的 TypeScript 客户端。 -
项目转型:如果你过去的项目使用过 Swagger Codegen,请注意它已被 OpenAPI Generator 取代,新项目应直接使用后者。
🎯 轻量之选:swagger-typescript-api
对于中小型项目或快速原型开发,追求简单直接,swagger-typescript-api 是一个足够轻便的选择。
-
配置简单:主要通过 CLI 命令运行,一条命令即可完成客户端生成。
-
功能聚焦:专注于生成函数式的 API 客户端,没有复杂的概念和配置,非常适合追求KISS原则的开发者。
💎 总结
从全链路类型安全和开箱即用的角度看,orval 依然是最能解决你核心痛点、与 Vue3 生态配合最紧密的选择。
不过,新的选择带来了新的视角。如果你的团队需要更高的可控性,或者项目是追求极致稳定的大型应用,@hey-api/openapi-ts 和 openapi-generator 也是非常值得投入的替代方案。
那vite-plugin-openapi-ts呢?
vite-plugin-openapi-ts 是一个很不错的发现。简单来说,它没有改变我们的结论,但它为我们选择 @hey-api/openapi-ts 并深度集成到 Vite 项目,提供了一个非常好的理由和捷径。
它并不是一个独立的工具,而是 @hey-api/openapi-ts 官方提供的 Vite 插件,作为你 Vue3 + Vite + TypeScript + Axios 技术栈的最佳拍档存在。为了让你更清晰地理解,我来将它纳入之前的对比框架,看看它具体带来了什么改变。
📊 核心方案对比速览
下表将 vite-plugin-openapi-ts 与之前讨论的核心方案放在一起,能让你直观地看到它的定位。
| 特性维度 | 🥇 orval | ⚙️ @hey-api/openapi-ts | 🎯 openapi-typescript |
|---|---|---|---|
| 定位 | 全链路、框架优先的客户端生成器,为现代前端框架深度优化 | 模块化、插件化的工具链,功能高度可定制 | 轻量、专注的 纯类型生成器 |
| Axios 集成 | 原生支持 (client: 'axios') | 支持,但需通过 @hey-api/client-axios 插件手动配置 | 不支持,需自己编写 Axios 请求逻辑 |
| Vue 3 生态 | 深度集成,可生成 TanStack Query 的 Vue Composable 钩子 | 中等集成,需自行配置 @tanstack/vue-query 插件 | 无,需自行封装 |
| 生成类型风格 | 生成完整的、可直接调用的 API SDK | 灵活,可生成 SDK 或纯类型 | 只生成纯类型定义 (.d.ts) |
| Vite 集成 | 无原生集成,需配合 npm 脚本或 vite-plugin-watch 等变通方法 | ✨ 官方原生 Vite 插件 (@hey-api/vite-plugin),实现自动化 | 无,需自行集成 |
| 配置复杂度 | 低,配置文件清晰 | 中高,功能强大但需理解插件系统 | 极低,配置简单 |
⚡️ 它就是你的“插件版”最优选:@hey-api/vite-plugin
vite-plugin-openapi-ts 真正强大的地方,在于它作为一个官方插件,解决了手动管理的痛点:
-
🔌 它是
@hey-api/openapi-ts的官方 Vite 插件:它的本质是@hey-api/vite-plugin,由@hey-api/openapi-ts官方维护。它不是野生的第三方插件,因此在稳定性、兼容性和更新上都有保障。 -
🚀 自动化工作流,开发体验极佳:它的核心价值在于自动化和集成。安装配置后,你只需像往常一样运行
npm run dev启动项目,插件就会自动根据 OpenAPI 文档生成类型和客户端。当你或后端同事更新了 OpenAPI 文档,插件能监听到变化并自动重新生成代码。它甚至能与 Vite 的 HMR 协同工作,整个过程你几乎无感知。
📝 核心配置速览:如何上手?
下面是一个最基础的配置示例,你可以把它保存为 vite.config.ts,集成成本非常低。
javascript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import openapi from '@hey-api/vite-plugin'; // 就是这个插件
export default defineConfig({
plugins: [
vue(),
openapi({
input: 'https://your-backend.com/api/openapi.json', // OpenAPI 文档地址
output: 'src/client', // 生成代码的存放路径
plugins: ['@hey-api/client-axios'], // 告诉它我们要生成 Axios 客户端
}),
],
});
如上所示,它的配置与 @hey-api/openapi-ts 的核心配置完全一致,学习成本几乎为零。
💡 那它和我们之前讨论的 orval 怎么选?
到这里,你可能会觉得这和 orval 很相似。它们的主要区别在于理念和偏好:
-
vite-plugin-openapi-ts(@hey-api/vite-plugin):基于@hey-api/openapi-ts,遵循“插件化、模块化”的设计哲学。如果你希望工具链像乐高积木一样,可以自由组合不同的功能插件(如生成 Axios 客户端、生成 TanStack Query Hooks、生成 Zod 校验器等),它会非常合适。 -
orval:追求“开箱即用、框架优先”的体验。如果你希望一个工具能智能地帮你处理好一切(特别是在TanStack Query的集成上非常出色),orval依然是绝佳的选择。
⚠️ 两个潜在的注意事项
在为你加分的同时,也有两个小点值得关注:
-
项目名称有“陷阱”:
vite-plugin-openapi-ts这个名称容易让人误以为它是openapi-typescript的插件,但实际上它是@hey-api/openapi-ts的官方插件。这点很重要,避免在搜索文档时走错方向。 -
@hey-api/openapi-ts的“双包”结构:在使用时,@hey-api/vite-plugin是 Vite 的集成层,而实际执行代码生成的核心引擎是@hey-api/openapi-ts,它在安装插件时会作为对等依赖被引入。理解这一点有助于排查问题。
🚀 集成步骤
对于你的技术栈,要集成 vite-plugin-openapi-ts,步骤很简单:
-
安装依赖:
bash
pnpm add -D @hey-api/vite-plugin @hey-api/openapi-ts
-
配置 Vite:在
vite.config.ts中如上所示配置插件即可。
总的来说,vite-plugin-openapi-ts 的出现,让你的技术栈多了一个极具竞争力的选择。你可以基于项目对框架集成深度和工具链灵活性的偏好,在它和 orval 之间做出最终的决定。
项目当前的情况,应该选择哪个最佳方案?
1、单人全栈项目,前端 Vue3+Vite+TypScript+Axios+Element-Plus,后端 Spring Boot 3.2.12+Mybatis-Plus
2、项目已经开发一段时间了
3、中途后端引进SpringDoc提供OpenAPI,前端引进openapi-typescript生成类型代码,在不改变原来代码的前提,可以直接上手使用
4、当前遇到的问题:openapi-typescript生成的联合类型 (Union Type),无法直接对应 Java 后端枚举的问题,openapi-typescript生成的联合类型无法对应Java枚举(命名映射问题)
明白了,你的情况很清晰:项目已开发一段时间,前端已经用 openapi-typescript 生成类型并配合手动 Axios 请求,现在唯一的问题是枚举类型映射不理想。 你希望尽量不改变现有代码,同时解决枚举问题。
基于这个约束,最佳方案不是 orval(它会生成完整的请求客户端,改动较大),也不是 openapi-typescript 本身(无法解决枚举问题)。最佳选择是:@hey-api/openapi-ts 的纯类型生成模式,保留你现有的 Axios 请求代码不变。
🎯 为什么这是最佳选择?
| 需求 | @hey-api/openapi-ts (纯类型模式) | orval | openapi-typescript |
|---|---|---|---|
| 不改变现有 Axios 请求代码 | ✅ 只生成类型,你继续用原来的请求代码 | ❌ 会生成完整的 SDK,需要替换请求调用 | ✅ 但枚举问题无解 |
| 解决 Java 枚举映射 | ✅ 可生成真正的 TypeScript enum | ✅ 也可生成枚举,但会连带生成请求代码 | ❌ 只能生成联合类型 |
| 迁移成本 | 低 – 只需替换类型引用路径 | 高 – 需要重构所有 API 调用 | 无(但问题没解决) |
| 与 Vite 集成 | 可选 @hey-api/vite-plugin 实现自动生成 | 需手动运行脚本 | 需手动运行脚本 |
简单来说:你只需要把类型生成工具从 openapi-typescript 换成 @hey-api/openapi-ts,并配置为只生成类型(包括枚举),你的 Axios 请求代码一行都不用改,枚举问题就解决了。
📝 具体操作步骤(迁移成本极小)
1. 安装依赖
bash
pnpm add -D @hey-api/openapi-ts # 如果希望自动监听变化,可以同时安装 vite 插件 pnpm add -D @hey-api/vite-plugin
2. 创建配置文件 hey-api.config.ts(放在项目根目录)
typescript
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: 'http://localhost:8080/v3/api-docs', // 你的 SpringDoc 地址
output: 'src/api/generated', // 生成类型的新目录
plugins: ['@hey-api/types'], // 只生成类型,不生成客户端
enums: {
mode: 'typescript', // 生成真正的 TS 枚举
},
});
3. 调整 package.json 脚本
json
"scripts": {
"gen-api": "hey-api -c hey-api.config.ts"
}
运行 pnpm run gen-api,就会在 src/api/generated 下生成:
-
types.ts:所有接口、模型的类型定义 -
各个枚举的
.ts文件(如果后端有枚举)
4. 修改前端代码中的类型引用
原来你是这样引用的:
typescript
import type { User, UserStatus } from './types/openapi'; // openapi-typescript 生成
现在改成:
typescript
import type { User } from '@/api/generated/types';
import { UserStatus } from '@/api/generated/UserStatus'; // 枚举
注意:由于 UserStatus 现在是一个真正的枚举,你在代码中如果之前是直接写字符串 'ACTIVE',现在可以继续写字符串(因为枚举值也是字符串),也可以换成 UserStatus.ACTIVE。两种方式都兼容,原有代码无需修改,因为 TypeScript 的字符串字面量可以赋值给枚举类型。
5. (可选)使用 Vite 插件实现自动生成
安装 @hey-api/vite-plugin,在 vite.config.ts 中添加:
typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import heyApi from '@hey-api/vite-plugin';
export default defineConfig({
plugins: [
vue(),
heyApi({
input: 'http://localhost:8080/v3/api-docs',
output: 'src/api/generated',
plugins: ['@hey-api/types'],
enums: { mode: 'typescript' },
}),
],
});
这样每次启动 npm run dev 或修改 OpenAPI 文档时,类型都会自动重新生成,开发体验更好。
❌ 为什么不选 orval 或 openapi-generator?
-
orval:虽然枚举支持好,但它默认会生成完整的 Axios 客户端代码。这意味着你需要把现有的所有 API 调用(例如axios.get('/users'))改成orval生成的getUsers()函数。对于已经开发一段时间的项目,这个重构成本太高,且容易引入 bug。 -
openapi-generator:同样会生成完整的客户端代码(基于类),并且生成的代码风格比较“Java 化”,与 Vue3 组合式 API 的风格不太协调。重构成本同样很高。 -
继续用
openapi-typescript+ 后处理脚本:理论上可以写脚本把联合类型转成枚举,但维护成本高,且不符合你“不改变原来代码”的初衷(脚本本身也算改动)。
✅ 总结:你的最佳行动路径
-
保留现有所有 Axios 请求代码不动。
-
用
@hey-api/openapi-ts的纯类型生成模式替换openapi-typescript,生成真正的 TypeScript 枚举。 -
修改类型导入路径(全局搜索替换即可,工作量极小)。
-
后续如果需要更高级的功能(如自动生成 TanStack Query hooks),可以再考虑迁移到
orval,但当前阶段完全没必要。
这样你既解决了枚举痛点,又保持了现有代码的稳定性,是单人全栈项目最务实的选择。
项目用的是npm
明白了,项目用的是 npm。那只需要把之前的 pnpm 命令换成 npm 即可,其他方案完全不变。
✅ 最佳方案确认:@hey-api/openapi-ts 纯类型生成模式
核心优势:只生成类型(含真正的 TypeScript 枚举),不生成请求客户端代码,你现有的 Axios 请求代码一行都不用改。
📦 具体操作步骤(npm 版)
1. 安装依赖
bash
npm install -D @hey-api/openapi-ts # 可选:Vite 插件实现自动监听 npm install -D @hey-api/vite-plugin
2. 创建配置文件 hey-api.config.ts
typescript
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: 'http://localhost:8080/v3/api-docs', // 你的 SpringDoc 地址
output: 'src/api/generated', // 新类型目录,与原来分开
plugins: ['@hey-api/types'], // 只生成类型
enums: {
mode: 'typescript', // 生成真正的 TS 枚举
},
});
3. 添加 npm 脚本
在 package.json 中:
json
"scripts": {
"gen-api": "hey-api -c hey-api.config.ts"
}
然后运行:
bash
npm run gen-api
4. 修改前端类型导入
原来(openapi-typescript 生成):
typescript
import type { User, UserStatus } from './types/openapi';
改为:
typescript
import type { User } from '@/api/generated/types';
import { UserStatus } from '@/api/generated/UserStatus'; // 枚举
兼容性说明:原有代码中如果写了
status: 'ACTIVE'这种字符串字面量,可以继续使用,因为 TypeScript 的字符串枚举值也是字符串,可以互相赋值。不需要立即改成UserStatus.ACTIVE。
5. (可选)使用 Vite 插件自动生成
安装插件后,在 vite.config.ts 中配置:
typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import heyApi from '@hey-api/vite-plugin';
export default defineConfig({
plugins: [
vue(),
heyApi({
input: 'http://localhost:8080/v3/api-docs',
output: 'src/api/generated',
plugins: ['@hey-api/types'],
enums: { mode: 'typescript' },
}),
],
});
之后每次运行 npm run dev,插件都会自动监听 OpenAPI 变化并重新生成类型。
❌ 为什么不选其他方案(再次确认)
| 方案 | 问题 |
|---|---|
orval | 会生成完整 SDK,需要重构所有 API 调用,改动太大 |
openapi-generator | 同样生成完整客户端,代码风格偏 Java,重构成本高 |
继续用 openapi-typescript | 枚举问题无解 |
| 自己写转换脚本 | 维护成本高,不如直接换工具 |
🎯 总结
你当前的唯一痛点是枚举映射,且希望最小改动。
@hey-api/openapi-ts 纯类型模式 是最优解:
-
✅ 解决枚举问题(生成真正的 TS
enum) -
✅ 不改变现有 Axios 请求代码
-
✅ 迁移成本极低(只需替换类型导入路径)
-
✅ 可选 Vite 插件实现自动化
按照上面的步骤操作,预计 10 分钟内就能完成迁移并解决枚举问题。
报错:
PS D:\MyCode\wylims-jm\lims-client> npm install -D @hey-api/openapi-ts
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: lims-client@0.0.0
npm error Found: typescript@5.4.5
npm error node_modules/typescript
npm error dev typescript@"~5.4.0" from the root project
npm error
npm error Could not resolve dependency:
npm error peer typescript@">=5.5.3 || >=6.0.0 || 6.0.1-rc" from @hey-api/openapi-ts@0.95.0
npm error node_modules/@hey-api/openapi-ts
npm error dev @hey-api/openapi-ts@"*" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error C:\Users\27973\AppData\Local\npm-cache\_logs\2026-04-06T01_30_13_218Z-eresolve-report.txt
npm error A complete log of this run can be found in: C:\Users\27973\AppData\Local\npm-cache\_logs\2026-04-06T01_30_13_218Z-debug-0.log
PS D:\MyCode\wylims-jm\lims-client>
这个报错是因为 TypeScript 版本不兼容:你项目中的 TypeScript 是 5.4.5,而 @hey-api/openapi-ts@0.95.0 要求 TypeScript >=5.5.3。
🔧 解决方案(按推荐程度排序)
方案一:升级 TypeScript(推荐)
升级到兼容的版本(如 5.6.3),通常小版本升级不会破坏现有代码。
bash
# 1. 升级 TypeScript npm install -D typescript@~5.6.0 # 2. 重新安装 @hey-api/openapi-ts npm install -D @hey-api/openapi-ts # 3. 运行生成命令 npm run gen-api
风险极低:TypeScript 从 5.4 到 5.6 没有破坏性变更,主要新增了功能和修复 bug。如果你的项目之前没有使用过 TS 5.5+ 的新特性,完全兼容。
方案二:使用 --legacy-peer-deps 强制安装(快速但不推荐)
如果暂时不想升级 TypeScript,可以绕过版本检查,但不保证完全兼容。
bash
npm install -D @hey-api/openapi-ts --legacy-peer-deps
⚠️ 潜在问题:@hey-api/openapi-ts 内部可能使用了 TypeScript 5.5+ 的 API,强制安装后运行时可能报错。
方案三:改用 orval(备选方案)
如果升级 TypeScript 有阻力,而 orval 对 TypeScript 版本要求更宽松(支持 5.0+),且同样支持枚举生成。不过它会生成完整的请求客户端,需要改动现有代码。
bash
npm install -D orval
配置 orval.config.ts 只生成类型(不生成客户端)?查一下:orval 默认生成客户端,没有纯类型模式。所以会导致需要重构 API 调用。因此不优先推荐。
方案四:继续使用 openapi-typescript + 后处理脚本(维持现状)
如果实在不想动依赖,可以写一个简单脚本,将 openapi-typescript 生成的联合类型转换成枚举。例如用 ts-morph 解析并重写。但维护成本高,且偏离“最佳方案”初衷。
✅ 最终建议
执行方案一:升级 TypeScript 到 ~5.6.0,然后正常安装 @hey-api/openapi-ts。这是最干净、最可持续的解法,且能让你后续享受工具的所有功能。
升级后,你的原有代码基本不会受影响,因为 TypeScript 小版本升级非常稳健。如果担心,可以先在分支上测试一下,运行 npm run build 确认无报错。
详情:
:解决openapi-typescript生成的联合类型无法对应Java枚举(命名映射问题)&spm=1001.2101.3001.5002&articleId=159857396&d=1&t=3&u=43aab3944f864630ae067015b0d74732)
753

被折叠的 条评论
为什么被折叠?



