背景:在前端开发中,后端API的类型定义一直是前后端协作的痛点。传统方式下,前端开发者需要手动编写和维护API请求参数和响应数据的类型定义,不仅工作繁琐,而且容易与后端实际接口产生不一致,导致类型错误难以发现。
为了解决这个问题,我探索了一条自动化生成TypeScript类型的完整流程:
graph LR
A["后端添加<br/>Swagger描述"] --> B["生成<br/>Swagger文档"]
B --> C["收集OpenAPI<br/>描述文件"]
C --> D["swagger-codegen-cli<br/>生成TS类型"]
D --> E["npm类型包<br/>@types规范命名"]
E --> F["发布到<br/>npm私服"]
F --> G["npm<br/>install"]
G --> H["前端<br/>import使用"]
通过这套流程,后端修改接口后,前端只需要重新安装最新的npm包即可获得最新的类型定义,真正实现了类型定义的自动化管理。
swagger
Swagger是一套用于构建、描述、测试和文档化RESTful API的开源框架。它通过在代码中添加注解(Annotations)来自动生成API文档,让后端开发者可以轻松地记录接口信息。
主流实现
- Java: SpringFox、Swagger Annotations
- Go: swaggo、go-swagger
- Python: flasgger、swagger-python
- Node.js: express-swagger-generator
基本注解示例
以Java SpringBoot为例:
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/users")
public class UserController {
@ApiOperation("获取用户详情")
@GetMapping("/{id}")
public User getUserById(@ApiParam("用户ID") @PathVariable Long id) {
return userService.getById(id);
}
@ApiOperation("创建用户")
@PostMapping
public Result<User> createUser(@RequestBody @Valid CreateUserRequest request) {
return Result.success(userService.create(request));
}
}
通过这些注解,Swagger会自动生成完整的API文档,包含请求参数、响应格式、错误码等详细信息。
OpenAPI
OpenAPI规范(原名Swagger规范)是一种与编程语言无关的REST API描述规范。它使用JSON或YAML格式来描述API的结构,包括:
- 接口路径(endpoints)
- HTTP方法(GET、POST、PUT、DELETE等)
- 请求参数和响应结构
- 认证方式
- 错误码定义
OpenAPI文档示例
openapi: 3.0.3
info:
title: 用户中心API
version: 1.0.0
paths:
/api/users/{id}:
get:
summary: 获取用户详情
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: 成功
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: integer
username:
type: string
email:
type: string
OpenAPI文档是整个自动化流程的核心,它作为中间桥梁连接了后端实现和前端类型生成。
实际中的swagger返回api描述:
自动生成类型的npm包
使用swagger-codegen-cli
我们使用swagger-codegen-cli-3.0.71.jar来从OpenAPI描述文件生成TypeScript类型定义。
生成命令
java -jar swagger-codegen-cli-3.0.71.jar generate \
-i openapi.json \
-l typescript \
-o ./src/types \
--additional-properties=modelPropertyNaming=camelCase,supportsES6=true
生成配置选项
| 参数 | 说明 | 可选值 |
|---|---|---|
| modelPropertyNaming | 属性命名风格 | camelCase、PascalCase、snake_case |
| supportsES6 | 是否支持ES6 | true、false |
| exportInterfaces | 是否导出接口 | true、false |
| enumPropertyNaming | 枚举命名风格 | camelCase、PascalCase、UPPER_CASE |
生成结果示例
生成的TypeScript类型文件:
export interface User {
id: number;
username: string;
email: string;
createdAt: string;
}
export interface CreateUserRequest {
username: string;
email: string;
password: string;
}
export interface Result<T> {
code: number;
message: string;
data: T;
}
发布npm包
命名规范
采用@types/{project}-{module}的命名风格,例如:
@types/user-center- 用户中心模块@types/order-system- 订单系统@types/product-api- 商品API
这样的命名方式:
- 符合npm社区对类型包的约定(@types前缀)
- 清晰表明是某个项目或模块的类型定义
- 便于前端按需安装
package.json配置
{
"name": "@types/user-center",
"version": "1.0.0",
"description": "用户中心API类型定义",
"main": "index.d.ts",
"types": "index.d.ts",
"publishConfig": {
"registry": "http://npm.internal.company.com/"
}
}
下面是我们实际项目中使用的一个示例:
发布到npm私服
# 登录npm仓库
npm login --registry=http://npm.internal.company.com/
# 发布包
npm publish --registry=http://npm.internal.company.com/
使用和更新
前端安装使用
npm install @types/user-center --save-dev --registry=http://npm.internal.company.com/
实际项目中的样子:
由截图可以看出由于按typescript的@types规范命名,其跟node的类型包一起放到了@types目录下,并且引入时不需要@types前缀
在代码中使用
- 引入,由于符合typescript的类型定义规范,所以可以直接引入类型包的名称而不需要@types前缀
- 使用,由引入可知,如果后端同学定义的类型全面的话会包含每个视图,接口的request,response,error等,所以前端在使用时只需要引入对应的类型即可,例如(这里我将引入的类型重新收集到了一个命名空间中了):
自动化更新流程
建议将类型生成集成到CI/CD流程中:
- 代码提交触发: 后端提交代码时自动运行
- 生成类型文件: 执行swagger-codegen生成新的类型定义
- 版本更新: 自动递增版本号
- 自动发布: 发布到npm私服
- 通知前端: 通知前端更新依赖,例如通过企业微信/钉钉通知前端更新依赖
# .gitlab-ci.yml 示例
generate-types:
stage: build
script:
- java -jar swagger-codegen-cli-3.0.71.jar generate \
-i api/openapi.json \
-l typescript \
-o ./types
- npm version patch
- npm publish --registry=http://npm.internal.company.com/
only:
- main
版本管理策略
- patch版本: 接口字段的增删改
- minor版本: 新增接口
- major版本: 不兼容的接口变更
总结
通过这套基于Swagger自动生成TypeScript类型的方案,我们实现了:
- 类型一致性: 前端使用的类型与后端API完全一致,避免了手动维护带来的不同步问题
- 开发效率提升: 后端修改接口后,前端可以快速获取最新的类型定义,减少沟通成本
- 自动化流程: 集成到CI/CD中,实现零手动干预的类型更新
- 规范统一: 统一的命名规范和包管理策略,便于项目管理和维护
- 协商协调: 前端和后端需要协商好类型定义的命名规范和位置,确保一致的使用,这需要前后端有很强的沟通意识,和规范的编码习惯。
这套方案特别适合中大型项目,能够有效提升前后端协作效率,减少因为类型不一致导致的线上bug。