使用 swagger-typescript-api 和 SWR 生成 TypeScript API 客户端教程
·
Swagger/OpenAPI 类型化 API 客户端生成指南
本教程将指导你如何使用 swagger-typescript-api 和 SWR 从 Swagger/OpenAPI 规范生成类型化的 API 客户端,并创建高效的 React 数据获取钩子。
目录
基础方案:swagger-typescript-api + 自定义 SWR 钩子
1. 安装依赖
npm install -g swagger-typescript-api
npm install swr # 如果你还没有安装 SWR
2. 生成 API 客户端
从 Swagger/OpenAPI 规范生成 TypeScript 客户端:
npx swagger-typescript-api -p ./openapi.yaml -o src/api -n api.ts
参数说明:
-p: OpenAPI 规范文件路径(可以是本地文件或远程 URL)-o: 输出目录-n: 输出文件名
3. 创建自定义 SWR 钩子
// src/hooks/useApi.ts
import useSWR from 'swr';
const fetcher = async (url: string, init?: RequestInit) => {
const res = await fetch(url, {
...init,
headers: {
'Content-Type': 'application/json',
...init?.headers,
},
});
if (!res.ok) {
throw new Error(await res.text());
}
return res.json();
};
export function useApi<T>(url?: string, enabled = true) {
const shouldFetch = enabled && !!url;
const { data, error, isLoading, mutate } = useSWR<T>(
shouldFetch ? url : null,
fetcher
);
return {
data,
error,
isLoading,
mutate,
isError: !!error,
};
}
4. 使用生成的 API 与自定义钩子
import { TradingApi } from '@/api/api'; // 生成的 API 客户端
import { useApi } from '@/hooks/useApi';
export function useUserInfo() {
const url = TradingApi.user.getUserInfo.path(); // 使用生成的路径方法
return useApi<UserInfo>(url);
}
// 在组件中使用
function UserProfile() {
const { data: user, isLoading, error } = useUserInfo();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
进阶方案:使用 orval 自动生成 SWR 钩子
1. 安装依赖
npm install -D orval
2. 配置 orval
创建 orval.config.ts 配置文件:
// orval.config.ts
export default {
trading: {
output: {
mode: 'tags-split', // 每个 tag 一个文件
target: './src/api/trading-api.ts',
schemas: './src/api/schema',
client: 'fetch',
mock: false,
override: {
mutator: {
path: './src/api/fetcher.ts',
name: 'customFetcher',
},
useHooks: true, // 启用 SWR hooks 生成
},
},
input: {
target: './openapi.yaml',
},
},
};
3. 创建自定义请求器
// src/api/fetcher.ts
export const customFetcher = async <TData>(
url: string,
options?: RequestInit,
): Promise<TData> => {
const res = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('token') || ''}`,
...options?.headers,
},
});
if (!res.ok) {
throw new Error(await res.text());
}
return res.json();
};
4. 生成 API 客户端和钩子
npx orval
5. 使用生成的钩子
生成的文件结构:
src/
├── api/
│ ├── trading-api/
│ │ ├── alarm.ts # 包含 useAlarmFindAlertPolicyList 等 hook
│ │ ├── auth.ts # 其他模块
│ ├── schema/ # 所有类型定义
│ └── fetcher.ts # 自定义请求器
使用示例:
import { useAlarmFindAlertPolicyList } from '@/api/trading-api/alarm';
function AlertPolicyList() {
const { data: policies, isLoading, error } = useAlarmFindAlertPolicyList({
query: {
offset: '0',
limit: '10',
},
});
if (isLoading) return <div>Loading policies...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{policies?.map(policy => (
<li key={policy.id}>{policy.name}</li>
))}
</ul>
);
}
两种方案对比
| 特性 | swagger-typescript-api + 自定义 SWR | orval 自动生成 SWR 钩子 |
|---|---|---|
| 安装复杂度 | 较低 | 中等(需要额外配置) |
| 自定义灵活性 | 高(完全控制钩子实现) | 中等(通过配置调整) |
| 生成代码量 | 较少(只生成 API 客户端) | 较多(生成完整钩子) |
| 维护成本 | 较高(需要手动维护钩子) | 低(自动生成) |
| 适合场景 | 需要高度自定义的简单项目 | 大型项目,快速开发 |
| 类型安全 | 是 | 是 |
| 自动生成请求/响应类型 | 是 | 是 |
推荐选择
选择基础方案 如果:
- 项目较小
- 需要高度自定义的请求逻辑
- 已经有一套自己的数据获取模式
选择进阶方案 如果:
- 项目较大,API 接口多
- 希望快速实现标准化 API 调用
- 需要减少样板代码
两种方案都能提供良好的类型安全性和开发体验,根据项目需求选择最适合的方式即可。
更多推荐



所有评论(0)