OpenAPI TS工具对比分析(获取适合项目实际情况的最佳方案@hey-api/openapi-ts):解决openapi-typescript生成的联合类型无法对应Java枚举(命名映射问题)

@hey-api/openapi-ts 并不是一个简单的“替换”,而是一次面向复杂需求的“升级”。 它是一个功能更全面的现代化工具集,与专注生成类型的 openapi-typescript 定位不同。

🔎 核心差异一览

下面的表格可以清晰地展示这两个工具的核心区别:

维度@hey-api/openapi-tsopenapi-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 能提供端到端的、无需代码生成的极致类型安全体验。

🤔 所以,我该怎么选?

你的选择取决于项目的具体需求和优先级:

  1. 我只需要静态类型,追求极致轻量
    选 openapi-typescript。它完美地做到了“一件事并把它做好”,没有任何运行时负担,适合任何需要 API 类型定义的项目。

  2. 我需要一套完整的解决方案,以提升团队效率
    选 @hey-api/openapi-ts。特别是当你的项目需要与 Fetch/Axios 客户端、TanStack Query 等框架深度集成时,它能为你生成所有胶水代码,极大提升开发效率。

  3. 我需要生成带有运行时校验的代码
    可以关注 vika-cli 这类能同时生成类型和 Zod 校验模式的新兴工具。

  4. 我追求端到端的极致类型安全,且能控制全栈
    可以考虑 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 枚举键名。这样一来,就实现了前后端枚举的解耦。

具体步骤如下:

  1. 后端定义 (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
  2. 配置 @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 的较新版本中已得到支持。

  3. 前端使用 (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-tsopenapi-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 中的枚举生成标准的 TypeScript enum,彻底解决你之前遇到的枚举问题,无需任何额外配置。

  • 配置简单,上手快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 依然是绝佳的选择。

⚠️ 两个潜在的注意事项

在为你加分的同时,也有两个小点值得关注:

  1. 项目名称有“陷阱”vite-plugin-openapi-ts 这个名称容易让人误以为它是 openapi-typescript 的插件,但实际上它是 @hey-api/openapi-ts 的官方插件。这点很重要,避免在搜索文档时走错方向。

  2. @hey-api/openapi-ts 的“双包”结构:在使用时,@hey-api/vite-plugin 是 Vite 的集成层,而实际执行代码生成的核心引擎是 @hey-api/openapi-ts,它在安装插件时会作为对等依赖被引入。理解这一点有助于排查问题。

🚀 集成步骤

对于你的技术栈,要集成 vite-plugin-openapi-ts,步骤很简单:

  1. 安装依赖

    bash

    pnpm add -D @hey-api/vite-plugin @hey-api/openapi-ts
  2. 配置 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 (纯类型模式)orvalopenapi-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 + 后处理脚本:理论上可以写脚本把联合类型转成枚举,但维护成本高,且不符合你“不改变原来代码”的初衷(脚本本身也算改动)。

✅ 总结:你的最佳行动路径

  1. 保留现有所有 Axios 请求代码不动

  2. 用 @hey-api/openapi-ts 的纯类型生成模式替换 openapi-typescript,生成真正的 TypeScript 枚举。

  3. 修改类型导入路径(全局搜索替换即可,工作量极小)。

  4. 后续如果需要更高级的功能(如自动生成 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 确认无报错。


详情:

https://chat.deepseek.com/share/enqyymfql7eczioywe

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值