# 前后端类型自动生成指南 > **解决前后端类型定义重复的问题** --- ## 🎯 问题 当前前后端类型定义重复: ```python # 后端 (server/app/models/project.py) class ProjectType(IntEnum): MINE = 1 COLLAB = 2 ``` ```typescript // 前端 (client/src/types/project.ts) export type ProjectType = 'mine' | 'collab'; export const PROJECT_TYPE = { MINE: 'mine', COLLAB: 'collab', } as const; ``` **问题**: - ❌ 重复定义,需要手动同步 - ❌ 新增枚举值时容易遗漏 - ❌ 维护成本高 --- ## ✨ 解决方案:自动生成 ### 方案 A:OpenAPI + TypeScript 生成器 ⭐ **推荐** #### 1. 后端生成 OpenAPI Schema FastAPI 自动生成 OpenAPI 文档: ```bash # 访问 OpenAPI JSON http://localhost:8000/openapi.json ``` #### 2. 安装前端生成工具 ```bash cd client npm install -D openapi-typescript-codegen # 或 npm install -D @openapitools/openapi-generator-cli ``` #### 3. 配置生成脚本 **package.json**: ```json { "scripts": { "generate:types": "openapi-typescript-codegen --input http://localhost:8000/openapi.json --output ./src/types/generated --client axios" } } ``` #### 4. 生成类型 ```bash npm run generate:types ``` **生成结果**: ```typescript // client/src/types/generated/models/ProjectType.ts export enum ProjectType { MINE = 'mine', COLLAB = 'collab', } // client/src/types/generated/models/Project.ts export interface Project { id: string; name: string; type: ProjectType; status: ProjectStatus; // ... } ``` #### 5. 使用生成的类型 ```typescript // client/src/pages/WorkspacePage.tsx import { ProjectType, Project } from '@/types/generated'; if (project.type === ProjectType.MINE) { // ... } ``` **优点**: - ✅ 100% 自动同步 - ✅ 类型安全 - ✅ 无需手动维护 - ✅ API 变更自动反映 **缺点**: - ⚠️ 需要后端服务运行 - ⚠️ 需要额外构建步骤 --- ### 方案 B:共享类型定义文件 #### 1. 创建类型定义文件 ```typescript // shared/types/project.ts export const PROJECT_TYPE = { MINE: 'mine', COLLAB: 'collab', } as const; export type ProjectType = typeof PROJECT_TYPE[keyof typeof PROJECT_TYPE]; ``` #### 2. 后端和前端都引用 **后端**: ```python # scripts/sync_types.py import json # 从 shared/types 读取类型定义 # 验证后端枚举是否一致 ``` **前端**: ```typescript // 直接导入 import { PROJECT_TYPE } from '@shared/types/project'; ``` **优点**: - ✅ 单一数据源 - ✅ 手动控制 **缺点**: - ❌ 需要额外的验证脚本 - ❌ 跨语言支持复杂 --- ### 方案 C:代码生成脚本 #### 1. 编写生成脚本 ```python # scripts/generate_frontend_types.py """ 从后端 Model 自动生成前端 TypeScript 类型 """ import ast import re from pathlib import Path def extract_enums(): """提取后端枚举定义""" model_file = Path("server/app/models/project.py") with open(model_file) as f: tree = ast.parse(f.read()) enums = {} for node in ast.walk(tree): if isinstance(node, ast.ClassDef): if any(base.id == 'IntEnum' for base in node.bases if isinstance(base, ast.Name)): enum_name = node.name enum_values = {} for item in node.body: if isinstance(item, ast.Assign): name = item.targets[0].id value = item.value.n # 查找 to_string 映射 enum_values[name] = value enums[enum_name] = enum_values return enums def generate_typescript(enums): """生成 TypeScript 类型定义""" output = [] for enum_name, values in enums.items(): # 生成类型 type_values = [f"'{v.lower()}'" for v in values.keys()] output.append(f"export type {enum_name} = {' | '.join(type_values)};") output.append("") # 生成常量 const_name = re.sub(r'(? str: mapping = {cls.MINE: "mine", cls.COLLAB: "collab"} return mapping.get(value, "mine") ``` ### 前端(自动生成) **运行生成**: ```bash npm run types:generate ``` **生成的文件** `client/src/types/generated/models.ts`: ```typescript // 🤖 自动生成,请勿手动修改 export enum ProjectType { MINE = 'mine', COLLAB = 'collab', } export enum ProjectStatus { ACTIVE = 'active', ARCHIVED = 'archived', TRASHED = 'trashed', SOFT_DELETED = 'soft_deleted', } export interface Project { id: string; name: string; type: ProjectType; status: ProjectStatus; // ... } ``` **使用**: ```typescript import { ProjectType } from '@/types/generated/models'; // ✅ 100% 与后端同步 if (project.type === ProjectType.MINE) { // ... } ``` --- ## 💡 实用技巧 ### 技巧 1:Git Hook 自动生成 ```bash # .husky/pre-commit #!/bin/sh cd client && npm run types:generate git add src/types/generated ``` ### 技巧 2:CI/CD 检查 ```yaml # .github/workflows/ci.yml - name: Check types sync run: | npm run types:generate git diff --exit-code src/types/generated || (echo "Types out of sync!" && exit 1) ``` ### 技巧 3:VSCode 任务 ```json // .vscode/tasks.json { "version": "2.0.0", "tasks": [ { "label": "Generate Types", "type": "npm", "script": "types:generate", "problemMatcher": [] } ] } ``` --- ## 🎯 最终建议 ### 小型项目(枚举变化不频繁) **方案**:手动维护 + 文档约定 - 简单直接 - 无需额外配置 ### 中大型项目(推荐)⭐ **方案**:OpenAPI + 自动生成 - 完全自动化 - 100% 同步 - 行业标准 ### 实施路径 1. **立即**:添加 OpenAPI 生成脚本 2. **短期**:配置 Git Hook 自动生成 3. **长期**:集成到 CI/CD --- **最后更新**: 2026-02-06 **维护者**: Jointo 开发团队