refactor(types): 重构类型系统,统一共享类型定义
feat(types): 新增共享类型中心,包含用户、产品、订单等核心领域类型 fix(types): 修复类型定义错误,统一各模块类型引用 style(types): 优化类型文件格式和注释 docs(types): 更新类型文档和变更日志 test(types): 添加类型测试用例 build(types): 配置类型共享路径 chore(types): 清理重复类型定义文件
This commit is contained in:
@@ -1,15 +1,75 @@
|
||||
# 架构文档索引
|
||||
|
||||
> **模块**: 01_Architecture - 系统架构设计
|
||||
> **更新日期**: 2026-03-21
|
||||
> **更新日期**: 2026-03-20
|
||||
|
||||
---
|
||||
|
||||
## 架构文档概览
|
||||
|
||||
架构文档包含系统架构、状态机、服务地图等核心设计文档,详细内容请参考全局文档索引。
|
||||
架构文档包含系统架构、状态机、服务地图、TypeScript 编译规约、代码质量规范等核心设计文档。
|
||||
|
||||
> **详细文档索引**:请参考 [全局文档索引](../10_Documents_Global/DOC_INDEX.md)
|
||||
---
|
||||
|
||||
## 核心文档
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [01_System.md](./01_System.md) | 系统架构:后端、前端、插件架构设计及依赖规则 |
|
||||
| [03_Domain_Model.md](./03_Domain_Model.md) | 领域模型:核心领域对象和关系定义 |
|
||||
| [06_State_Machine.md](./06_State_Machine.md) | 状态机:商户、用户、店铺、订单等状态机定义 |
|
||||
| [07_SEMANTIC_HUB.md](./07_SEMANTIC_HUB.md) | 语义中心:统一全局语义定义,确保AI开发一致性 |
|
||||
|
||||
---
|
||||
|
||||
## TypeScript 与代码质量
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [13_TypeScript_Standards.md](./13_TypeScript_Standards.md) | **TypeScript 编译规约**:TypeScript 编译零错误规约体系、tsconfig 配置、代码规约 |
|
||||
| [14_Code_Quality_Standards.md](./14_Code_Quality_Standards.md) | **代码质量规范**:ESLint 配置、Prettier 配置、代码风格规范、测试规范 |
|
||||
| [15_Schema_Driven_Development.md](./15_Schema_Driven_Development.md) | **Schema 驱动开发**:zod 使用指南、Schema 组织、类型推导、数据验证 |
|
||||
| [16_Unified_Type_Management.md](./16_Unified_Type_Management.md) | **统一类型管理**:类型中心架构、类型层次、类型转换、版本管理 |
|
||||
|
||||
---
|
||||
|
||||
## 业务规则与权限
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [08_BILLING_RULES.md](./08_BILLING_RULES.md) | 计费规则:订阅计费、功能计费、API 计费规则 |
|
||||
| [09_PERMISSION_RULES.md](./09_PERMISSION_RULES.md) | 权限规则:RBAC 权限模型、角色定义、权限校验规则 |
|
||||
|
||||
---
|
||||
|
||||
## 系统设计
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [02_System_Interoperability.md](./02_System_Interoperability.md) | 系统互通架构:系统各组件之间的互通机制和通信规范 |
|
||||
| [04_Service_Map.md](./04_Service_Map.md) | 服务地图:后端服务接口映射和依赖关系 |
|
||||
| [05_Module_Blueprints.md](./05_Module_Blueprints.md) | 模块蓝图:OMS, WMS, Finance, MKT 等模块的前端集成蓝图 |
|
||||
|
||||
---
|
||||
|
||||
## 专项架构
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [10_Currency_Management.md](./10_Currency_Management.md) | 货币管理:多货币支持、汇率管理、货币转换 |
|
||||
| [11_Mock_Architecture.md](./11_Mock_Architecture.md) | Mock 架构:低侵入 Mock 方案,支持 DataSource 内联和 MSW 网络层两种方式 |
|
||||
| [12_Operation_Agent.md](./12_Operation_Agent.md) | 运营 Agent:运营自动化、Agent 设计、任务调度 |
|
||||
|
||||
---
|
||||
|
||||
## 前端架构
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [frontend/01_Product.md](./frontend/01_Product.md) | 产品前端:产品模块前端设计规范 |
|
||||
| [frontend/02_Orders.md](./frontend/02_Orders.md) | 订单前端:订单模块前端设计规范 |
|
||||
| [frontend/03_Ad.md](./frontend/03_Ad.md) | 广告前端:广告模块前端设计规范 |
|
||||
| [frontend/04_IndependentSite.md](./frontend/04_IndependentSite.md) | 独立站点前端:独立站点模块前端设计规范 |
|
||||
|
||||
---
|
||||
|
||||
@@ -23,5 +83,6 @@
|
||||
|
||||
## 最近更新
|
||||
|
||||
- 2026-03-21: 简化文档索引,引用全局DOC_INDEX.md
|
||||
- 2026-03-20: 新增 TypeScript 编译规约、代码质量规范、Schema 驱动开发、统一类型管理文档
|
||||
- 2026-03-21: 简化文档索引,引用全局 DOC_INDEX.md
|
||||
- 2026-03-19: 重构架构文档结构,统一命名规范
|
||||
|
||||
718
docs/01_Architecture/13_TypeScript_Standards.md
Normal file
718
docs/01_Architecture/13_TypeScript_Standards.md
Normal file
@@ -0,0 +1,718 @@
|
||||
# TypeScript 编译规约(TypeScript Compilation Standards)
|
||||
|
||||
> **模块**: 01_Architecture - TypeScript 编译零错误规约体系
|
||||
> **更新日期**: 2026-03-20
|
||||
> **适用范围**: 全项目(dashboard、server、extension、node-agent)
|
||||
|
||||
---
|
||||
|
||||
## 1. 核心原则(Core Principles)
|
||||
|
||||
### 1.1 强制认知统一
|
||||
|
||||
| 原则 | 说明 | 违反后果 |
|
||||
|------|------|----------|
|
||||
| **不允许 any** | 禁止使用 `any` 类型,使用 `unknown` 替代 | 类型安全完全丧失 |
|
||||
| **不允许隐式类型推断** | 在边界层(API、DTO)必须显式声明类型 | 类型推断污染调用链 |
|
||||
| **所有数据都有来源定义** | 数据必须通过 Schema / DTO / 类型定义 | 运行时类型错误 |
|
||||
| **编译错误 = 构建失败** | TypeScript 编译错误必须阻断 CI/CD | 低质量代码进入生产 |
|
||||
| **类型错误优先级 > 运行时错误** | 优先解决类型问题,而非运行时问题 | 难以调试和维护 |
|
||||
|
||||
### 1.2 类型边界分层
|
||||
|
||||
必须把类型分成 3 层:
|
||||
|
||||
```
|
||||
接口层(API) → DTO层 → 业务层(Domain)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```typescript
|
||||
// ❌ 错误写法(直接用接口数据)
|
||||
const price = res.price * 100
|
||||
|
||||
// ✅ 正确:必须经过 DTO 转换
|
||||
type ProductDTO = {
|
||||
price: number
|
||||
}
|
||||
|
||||
function transformProduct(data: unknown): ProductDTO {
|
||||
if (typeof data !== 'object' || data === null) {
|
||||
throw new Error('Invalid product data')
|
||||
}
|
||||
|
||||
const productData = data as Record<string, unknown>
|
||||
|
||||
return {
|
||||
price: Number(productData.price) || 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 规则
|
||||
|
||||
- **接口返回 = 不可信**
|
||||
- **必须经过 transform 才能进入业务层**
|
||||
- **禁止在业务层直接使用 API 返回的数据**
|
||||
|
||||
---
|
||||
|
||||
## 2. tsconfig 强约束配置(第一道防线)
|
||||
|
||||
### 2.1 生产级严格配置
|
||||
|
||||
所有模块的 `tsconfig.json` 必须包含以下配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 关键约束解释
|
||||
|
||||
| 配置项 | 作用 | 防止的问题 |
|
||||
|--------|------|------------|
|
||||
| `noUncheckedIndexedAccess` | 防止 `obj[key]` 直接 undefined 崩溃 | 运行时 undefined 错误 |
|
||||
| `exactOptionalPropertyTypes` | `?` 不再等于 `undefined \| T` | 脏数据污染 |
|
||||
| `isolatedModules` | 防止某些文件在构建工具中行为不一致 | 构建不一致 |
|
||||
| `strictNullChecks` | 严格检查 null 和 undefined | 空指针异常 |
|
||||
| `noImplicitReturns` | 禁止函数隐式返回 | 返回值类型错误 |
|
||||
|
||||
### 2.3 各模块配置差异
|
||||
|
||||
#### Dashboard(前端)
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"jsx": "react-jsx",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Server(后端)
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "CommonJS",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"useDefineForClassFields": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Extension(浏览器插件)
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"jsx": "react-jsx",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Node-Agent(Node.js 代理)
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2022"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 代码规约(真正减少 80% 错误)
|
||||
|
||||
### 3.1 禁止裸对象(必须类型化)
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
const user = { name: 'xx', age: 18 }
|
||||
|
||||
// ✅ 正确
|
||||
type User = {
|
||||
name: string
|
||||
age: number
|
||||
}
|
||||
const user: User = { name: 'xx', age: 18 }
|
||||
```
|
||||
|
||||
### 3.2 函数必须声明返回类型
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
function getPrice() {
|
||||
return 100
|
||||
}
|
||||
|
||||
// ✅ 正确
|
||||
function getPrice(): number {
|
||||
return 100
|
||||
}
|
||||
```
|
||||
|
||||
**原因**:防止隐式推断污染调用链
|
||||
|
||||
### 3.3 所有 API 层必须定义类型
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
axios.get('/api')
|
||||
|
||||
// ✅ 正确
|
||||
interface ApiResponse<T> {
|
||||
code: string
|
||||
message: string
|
||||
data: T
|
||||
}
|
||||
|
||||
interface Product {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
axios.get<ApiResponse<Product>>('/api')
|
||||
```
|
||||
|
||||
### 3.4 禁止 any(用 unknown 替代)
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
function handle(data: any) {
|
||||
return data.price
|
||||
}
|
||||
|
||||
// ✅ 正确
|
||||
function handle(data: unknown) {
|
||||
if (typeof data === 'object' && data !== null && 'price' in data) {
|
||||
return (data as { price: unknown }).price
|
||||
}
|
||||
throw new Error('Invalid data')
|
||||
}
|
||||
```
|
||||
|
||||
**类型收窄**:使用 `typeof`、`instanceof`、`in` 操作符进行类型收窄
|
||||
|
||||
### 3.5 枚举/常量统一化(避免字符串错误)
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
if (status === 'success') {
|
||||
// ...
|
||||
}
|
||||
|
||||
// ✅ 正确
|
||||
enum Status {
|
||||
Success = 'success',
|
||||
Failed = 'failed',
|
||||
Pending = 'pending'
|
||||
}
|
||||
|
||||
if (status === Status.Success) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 类型守卫(Type Guards)
|
||||
|
||||
```typescript
|
||||
interface Product {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
function isProduct(data: unknown): data is Product {
|
||||
return (
|
||||
typeof data === 'object' &&
|
||||
data !== null &&
|
||||
'id' in data &&
|
||||
'name' in data &&
|
||||
'price' in data &&
|
||||
typeof (data as Product).id === 'string' &&
|
||||
typeof (data as Product).name === 'string' &&
|
||||
typeof (data as Product).price === 'number'
|
||||
)
|
||||
}
|
||||
|
||||
function handleData(data: unknown) {
|
||||
if (isProduct(data)) {
|
||||
// TypeScript 知道 data 是 Product 类型
|
||||
console.log(data.name)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. ESLint + TypeScript 规则(第二道防线)
|
||||
|
||||
### 4.1 必须安装的依赖
|
||||
|
||||
```bash
|
||||
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
||||
```
|
||||
|
||||
### 4.2 .eslintrc.js 核心规则
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: __dirname
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/explicit-function-return-type': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
'@typescript-eslint/no-misused-promises': 'error',
|
||||
'@typescript-eslint/strict-boolean-expressions': 'error',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
||||
'prettier/prettier': 'error'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 规则说明
|
||||
|
||||
| 规则 | 作用 | 优先级 |
|
||||
|------|------|--------|
|
||||
| `@typescript-eslint/no-explicit-any` | 禁止使用 `any` | P0 |
|
||||
| `@typescript-eslint/explicit-function-return-type` | 强制声明函数返回类型 | P0 |
|
||||
| `@typescript-eslint/consistent-type-imports` | 统一 import 语法 | P1 |
|
||||
| `@typescript-eslint/no-floating-promises` | 禁止未处理的 Promise | P0 |
|
||||
| `@typescript-eslint/strict-boolean-expressions` | 严格布尔表达式 | P1 |
|
||||
|
||||
**作用**:在**写代码时就报错(不是编译时)**
|
||||
|
||||
---
|
||||
|
||||
## 5. 提交前拦截(第三道防线)
|
||||
|
||||
### 5.1 安装依赖
|
||||
|
||||
```bash
|
||||
npm install -D husky lint-staged
|
||||
```
|
||||
|
||||
### 5.2 package.json 配置
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"prepare": "husky install",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": [
|
||||
"eslint --fix",
|
||||
"tsc --noEmit"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 启用 Husky 钩子
|
||||
|
||||
```bash
|
||||
npx husky install
|
||||
npx husky add .husky/pre-commit "npx lint-staged"
|
||||
```
|
||||
|
||||
### 5.4 效果
|
||||
|
||||
- 提交代码前自动检查
|
||||
- 有 TS 错误直接不让 commit
|
||||
- 自动修复可修复的 ESLint 错误
|
||||
|
||||
---
|
||||
|
||||
## 6. CI/CD 阶段强制校验(最终防线)
|
||||
|
||||
### 6.1 TypeScript 编译检查
|
||||
|
||||
```bash
|
||||
tsc --noEmit
|
||||
```
|
||||
|
||||
### 6.2 CI/CD 配置(GitHub Actions 示例)
|
||||
|
||||
```yaml
|
||||
name: TypeScript CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
|
||||
jobs:
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
module: [dashboard, server, extension, node-agent]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: ${{ matrix.module }}/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./${{ matrix.module }}
|
||||
run: npm ci
|
||||
|
||||
- name: Run ESLint
|
||||
working-directory: ./${{ matrix.module }}
|
||||
run: npm run lint
|
||||
|
||||
- name: Type check
|
||||
working-directory: ./${{ matrix.module }}
|
||||
run: npm run typecheck
|
||||
|
||||
- name: Build
|
||||
working-directory: ./${{ matrix.module }}
|
||||
run: npm run build
|
||||
```
|
||||
|
||||
### 6.3 验证标准
|
||||
|
||||
- ❌ 有错误 → 构建失败
|
||||
- ✅ 0 errors → 才能发布
|
||||
|
||||
---
|
||||
|
||||
## 7. 架构级避免错误
|
||||
|
||||
### 7.1 Schema 驱动(强烈建议)
|
||||
|
||||
使用 **zod** 或 **class-validator** 进行运行时校验 + 编译时类型统一
|
||||
|
||||
#### 使用 zod
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const ProductSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string().min(1),
|
||||
price: z.number().positive(),
|
||||
stock: z.number().int().nonnegative()
|
||||
})
|
||||
|
||||
type Product = z.infer<typeof ProductSchema>
|
||||
|
||||
// 使用
|
||||
function validateProduct(data: unknown): Product {
|
||||
return ProductSchema.parse(data)
|
||||
}
|
||||
```
|
||||
|
||||
#### 使用 class-validator
|
||||
|
||||
```typescript
|
||||
import { IsString, IsNumber, Min, IsUUID } from 'class-validator'
|
||||
|
||||
class ProductDTO {
|
||||
@IsUUID()
|
||||
id: string
|
||||
|
||||
@IsString()
|
||||
name: string
|
||||
|
||||
@IsNumber()
|
||||
@Min(0)
|
||||
price: number
|
||||
|
||||
@IsNumber()
|
||||
@Min(0)
|
||||
stock: number
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 统一类型中心(Semantic Hub)
|
||||
|
||||
所有类型只允许从 `/types` 目录 import,禁止各模块自己定义
|
||||
|
||||
#### 目录结构
|
||||
|
||||
```
|
||||
/types
|
||||
/api # API 接口类型
|
||||
/dto # 数据传输对象
|
||||
/domain # 领域模型类型
|
||||
/shared # 共享类型
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```typescript
|
||||
// ❌ 错误:各模块自己定义类型
|
||||
// dashboard/src/pages/Product/Product.tsx
|
||||
interface Product {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
// server/src/models/Product.ts
|
||||
interface Product {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
// ✅ 正确:统一类型中心
|
||||
// types/domain/Product.ts
|
||||
export interface Product {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
stock: number
|
||||
}
|
||||
|
||||
// dashboard/src/pages/Product/Product.tsx
|
||||
import { Product } from '@/types/domain/Product'
|
||||
|
||||
// server/src/models/Product.ts
|
||||
import { Product } from '@/types/domain/Product'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 终极落地流程
|
||||
|
||||
### 8.1 开发流程
|
||||
|
||||
```
|
||||
写代码
|
||||
↓
|
||||
ESLint 实时报错
|
||||
↓
|
||||
提交前 lint-staged 拦截
|
||||
↓
|
||||
CI 执行 tsc
|
||||
↓
|
||||
部署
|
||||
```
|
||||
|
||||
### 8.2 错误处理优先级
|
||||
|
||||
| 优先级 | 错误类型 | 处理方式 |
|
||||
|--------|----------|----------|
|
||||
| P0 | TypeScript 编译错误 | 立即修复,阻断提交 |
|
||||
| P1 | ESLint 错误 | 立即修复,阻断提交 |
|
||||
| P2 | ESLint 警告 | 建议修复,不阻断 |
|
||||
| P3 | 代码风格问题 | 自动修复或手动调整 |
|
||||
|
||||
---
|
||||
|
||||
## 9. AI 代码生成规范
|
||||
|
||||
### 9.1 AI 生成代码必须遵守
|
||||
|
||||
1. **类型完整性**:所有函数、变量、参数必须有明确类型
|
||||
2. **类型安全**:禁止使用 `any`,使用 `unknown` + 类型守卫
|
||||
3. **边界检查**:所有外部数据必须经过 Schema 验证
|
||||
4. **错误处理**:所有可能失败的操作必须有错误处理
|
||||
5. **注释规范**:复杂逻辑必须有 JSDoc 注释
|
||||
|
||||
### 9.2 AI 代码自动校验流程
|
||||
|
||||
```
|
||||
AI 生成代码
|
||||
↓
|
||||
自动运行 tsc --noEmit
|
||||
↓
|
||||
自动运行 eslint --fix
|
||||
↓
|
||||
有错误 → 自动修复或标记为失败
|
||||
↓
|
||||
无错误 → 标记为通过
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 常见错误与解决方案
|
||||
|
||||
### 10.1 类型不兼容
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
const price: number = '100'
|
||||
|
||||
// ✅ 正确
|
||||
const price: number = Number('100') || 0
|
||||
```
|
||||
|
||||
### 10.2 可能为 null/undefined
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
const product = getProduct()
|
||||
console.log(product.name)
|
||||
|
||||
// ✅ 正确
|
||||
const product = getProduct()
|
||||
if (product) {
|
||||
console.log(product.name)
|
||||
}
|
||||
|
||||
// 或使用可选链
|
||||
console.log(product?.name)
|
||||
```
|
||||
|
||||
### 10.3 数组索引访问
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
const firstItem = items[0]
|
||||
console.log(firstItem.name)
|
||||
|
||||
// ✅ 正确
|
||||
const firstItem = items[0]
|
||||
if (firstItem) {
|
||||
console.log(firstItem.name)
|
||||
}
|
||||
|
||||
// 或使用非空断言(谨慎使用)
|
||||
const firstItem = items[0]!
|
||||
console.log(firstItem.name)
|
||||
```
|
||||
|
||||
### 10.4 Promise 未处理
|
||||
|
||||
```typescript
|
||||
// ❌ 错误
|
||||
fetch('/api/data')
|
||||
|
||||
// ✅ 正确
|
||||
fetch('/api/data')
|
||||
.then(res => res.json())
|
||||
.catch(err => console.error(err))
|
||||
|
||||
// 或使用 async/await
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await fetch('/api/data')
|
||||
return await res.json()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 性能优化建议
|
||||
|
||||
### 11.1 类型推断优化
|
||||
|
||||
```typescript
|
||||
// ❌ 错误:过度类型注解
|
||||
const numbers: number[] = [1, 2, 3]
|
||||
|
||||
// ✅ 正确:让 TypeScript 推断
|
||||
const numbers = [1, 2, 3]
|
||||
```
|
||||
|
||||
### 11.2 避免类型断言
|
||||
|
||||
```typescript
|
||||
// ❌ 错误:过度使用类型断言
|
||||
const product = data as Product
|
||||
|
||||
// ✅ 正确:使用类型守卫
|
||||
if (isProduct(data)) {
|
||||
const product = data
|
||||
}
|
||||
```
|
||||
|
||||
### 11.3 使用泛型
|
||||
|
||||
```typescript
|
||||
// ❌ 错误:重复代码
|
||||
function getNumberArray(): number[] {
|
||||
return [1, 2, 3]
|
||||
}
|
||||
|
||||
function getStringArray(): string[] {
|
||||
return ['a', 'b', 'c']
|
||||
}
|
||||
|
||||
// ✅ 正确:使用泛型
|
||||
function getArray<T>(items: T[]): T[] {
|
||||
return items
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 版本管理
|
||||
|
||||
| 版本 | 变更内容 | 日期 |
|
||||
|------|----------|------|
|
||||
| 1.0.0 | 初始版本 | 2026-03-20 |
|
||||
|
||||
---
|
||||
|
||||
## 13. 参考资源
|
||||
|
||||
- [TypeScript 官方文档](https://www.typescriptlang.org/docs/)
|
||||
- [TypeScript ESLint 规则](https://typescript-eslint.io/rules/)
|
||||
- [zod 文档](https://zod.dev/)
|
||||
- [Husky 文档](https://typicode.github.io/husky/)
|
||||
- [lint-staged 文档](https://github.com/okonet/lint-staged)
|
||||
1021
docs/01_Architecture/14_Code_Quality_Standards.md
Normal file
1021
docs/01_Architecture/14_Code_Quality_Standards.md
Normal file
File diff suppressed because it is too large
Load Diff
1029
docs/01_Architecture/15_Schema_Driven_Development.md
Normal file
1029
docs/01_Architecture/15_Schema_Driven_Development.md
Normal file
File diff suppressed because it is too large
Load Diff
594
docs/01_Architecture/16_Unified_Type_Management.md
Normal file
594
docs/01_Architecture/16_Unified_Type_Management.md
Normal file
@@ -0,0 +1,594 @@
|
||||
# 统一类型管理规范(Unified Type Management Standards)
|
||||
|
||||
> **模块**: 01_Architecture - 统一类型管理与语义中心
|
||||
> **更新日期**: 2026-03-20
|
||||
> **版本**: 1.0.0
|
||||
> **适用范围**: 全项目(dashboard、server、extension)
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述(Overview)
|
||||
|
||||
### 1.1 什么是统一类型管理
|
||||
|
||||
**统一类型管理**是一种集中式类型定义和管理的方法,通过建立统一的类型中心来:
|
||||
|
||||
- **消除类型重复**:避免在多个模块中重复定义相同类型
|
||||
- **确保类型一致性**:前后端使用相同的类型定义
|
||||
- **提高可维护性**:类型变更只需修改一处
|
||||
- **增强类型安全**:通过 Schema 驱动确保类型正确性
|
||||
- **AI 友好**:为 AI 提供清晰、统一的类型定义
|
||||
|
||||
### 1.2 核心原则
|
||||
|
||||
| 原则 | 说明 | 违反后果 |
|
||||
|------|------|----------|
|
||||
| **单一来源** | 所有类型只从类型中心导入 | 类型不一致 |
|
||||
| **禁止重复定义** | 禁止在各模块中重复定义类型 | 维护困难 |
|
||||
| **Schema 驱动** | 类型从 Schema 推导而来 | 类型错误 |
|
||||
| **分层管理** | 按层次组织类型(API、DTO、Domain) | 结构混乱 |
|
||||
| **版本控制** | 类型变更必须版本化 | 兼容性问题 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前实现架构(Current Implementation)
|
||||
|
||||
### 2.1 目录结构
|
||||
|
||||
```
|
||||
server/src/shared/
|
||||
├── schemas/ # ✅ Zod Schema 定义中心(唯一真理源)
|
||||
│ ├── user.schema.ts # User Schema + 类型推导
|
||||
│ ├── product.schema.ts # Product Schema + 类型推导
|
||||
│ ├── order.schema.ts # Order Schema + 类型推导
|
||||
│ ├── message.schema.ts # 插件消息类型
|
||||
│ ├── common.schema.ts # 通用类型(分页、错误等)
|
||||
│ └── index.ts # 统一导出
|
||||
│
|
||||
├── types/ # 类型重新导出(兼容层)
|
||||
│ ├── domain/ # 领域模型(从 Schema 推导)
|
||||
│ │ ├── User.ts
|
||||
│ │ ├── Product.ts
|
||||
│ │ ├── Order.ts
|
||||
│ │ ├── Inventory.ts
|
||||
│ │ ├── ShopInfo.ts
|
||||
│ │ ├── Certificate.ts
|
||||
│ │ └── ProductSelection.ts
|
||||
│ ├── dto/ # 数据传输对象(从 Schema 推导)
|
||||
│ │ ├── UserDTO.ts
|
||||
│ │ ├── ProductDTO.ts
|
||||
│ │ ├── OrderDTO.ts
|
||||
│ │ └── index.ts
|
||||
│ ├── enums/ # 枚举定义
|
||||
│ │ ├── BusinessEnums.ts
|
||||
│ │ ├── PlatformType.ts
|
||||
│ │ ├── StoreStatus.ts
|
||||
│ │ └── index.ts
|
||||
│ ├── shared/ # 共享类型
|
||||
│ │ ├── Message.ts
|
||||
│ │ ├── DataSource.ts
|
||||
│ │ ├── Monitoring.ts
|
||||
│ │ ├── Security.ts
|
||||
│ │ ├── Service.ts
|
||||
│ │ ├── Pagination.ts
|
||||
│ │ ├── Error.ts
|
||||
│ │ ├── Response.ts
|
||||
│ │ └── index.ts
|
||||
│ ├── version.ts # 类型版本管理
|
||||
│ └── index.ts # 统一导出
|
||||
│
|
||||
└── utils/
|
||||
└── zodToOpenAPI.ts # Zod → OpenAPI 转换工具
|
||||
|
||||
dashboard/src/types/
|
||||
├── dataSourceMap.ts # DataSource 类型映射
|
||||
└── index.ts # 重新导出 server 类型
|
||||
|
||||
extension/src/types/
|
||||
└── index.ts # 重新导出 server 类型
|
||||
```
|
||||
|
||||
### 2.2 类型层次
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Zod Schema(唯一真理源) │
|
||||
│ - 运行时验证 │
|
||||
│ - 类型推导 │
|
||||
└──────────────┬──────────────────────────┘
|
||||
│ z.infer<typeof Schema>
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Domain Layer (领域层) │
|
||||
│ - Business Entities │
|
||||
│ - Domain Models │
|
||||
└──────────────┬──────────────────────────┘
|
||||
│
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ DTO Layer (传输层) │
|
||||
│ - Data Transfer Objects │
|
||||
│ - API Input/Output │
|
||||
└──────────────┬──────────────────────────┘
|
||||
│
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ API Layer (接口层) │
|
||||
│ - Request Types │
|
||||
│ - Response Types │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Schema 驱动开发(Schema-Driven Development)
|
||||
|
||||
### 3.1 定义 Schema
|
||||
|
||||
```typescript
|
||||
// server/src/shared/schemas/user.schema.ts
|
||||
import { z } from 'zod';
|
||||
|
||||
export const UserRoleSchema = z.enum([
|
||||
'admin',
|
||||
'customer',
|
||||
'manager',
|
||||
'staff',
|
||||
'finance',
|
||||
'sourcing',
|
||||
'logistics',
|
||||
'analyst'
|
||||
]);
|
||||
|
||||
export const UserStatusSchema = z.enum([
|
||||
'active',
|
||||
'inactive',
|
||||
'suspended'
|
||||
]);
|
||||
|
||||
export const UserSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
phone: z.string().optional(),
|
||||
role: UserRoleSchema,
|
||||
status: UserStatusSchema,
|
||||
createdAt: z.coerce.date(),
|
||||
updatedAt: z.coerce.date()
|
||||
});
|
||||
|
||||
// 自动推导类型
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
export type UserRole = z.infer<typeof UserRoleSchema>;
|
||||
export type UserStatus = z.infer<typeof UserStatusSchema>;
|
||||
```
|
||||
|
||||
### 3.2 DTO 层从 Schema 推导
|
||||
|
||||
```typescript
|
||||
// server/src/shared/types/dto/UserDTO.ts
|
||||
import type {
|
||||
User,
|
||||
UserRole,
|
||||
UserStatus,
|
||||
CreateUserInput,
|
||||
UpdateUserInput,
|
||||
UserQueryInput
|
||||
} from '../../schemas/user.schema';
|
||||
|
||||
export type {
|
||||
User,
|
||||
UserRole,
|
||||
UserStatus,
|
||||
CreateUserInput as CreateUserDTO,
|
||||
UpdateUserInput as UpdateUserDTO,
|
||||
UserQueryInput as UserQueryDTO
|
||||
};
|
||||
|
||||
export interface UserResponseDTO extends User {}
|
||||
```
|
||||
|
||||
### 3.3 Domain 层从 Schema 推导
|
||||
|
||||
```typescript
|
||||
// server/src/shared/types/domain/User.ts
|
||||
export type {
|
||||
User,
|
||||
UserRole,
|
||||
UserStatus
|
||||
} from '../../schemas/user.schema';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API 验证(API Validation)
|
||||
|
||||
### 4.1 使用 Zod 验证中间件
|
||||
|
||||
```typescript
|
||||
// server/src/api/routes/user.ts
|
||||
import { Router } from 'express';
|
||||
import { validateSchema } from '../middleware/ZodValidationMiddleware';
|
||||
import { CreateUserSchema, UpdateUserSchema } from '@shared/schemas';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
'/users',
|
||||
validateSchema(CreateUserSchema),
|
||||
UserController.create
|
||||
);
|
||||
|
||||
router.put(
|
||||
'/users/:id',
|
||||
validateSchema(UpdateUserSchema),
|
||||
UserController.update
|
||||
);
|
||||
```
|
||||
|
||||
### 4.2 验证中间件实现
|
||||
|
||||
```typescript
|
||||
// server/src/api/middleware/ZodValidationMiddleware.ts
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { ZodObject, ZodError } from 'zod';
|
||||
|
||||
export const validateSchema = (schema: ZodObject<any>) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
await schema.parseAsync({
|
||||
body: req.body,
|
||||
query: req.query,
|
||||
params: req.params,
|
||||
});
|
||||
next();
|
||||
} catch (error) {
|
||||
if (error instanceof ZodError) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'BAD_REQUEST_INVALID_SCHEMA',
|
||||
message: '请求参数不符合 API 契约规范',
|
||||
details: error.issues
|
||||
});
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 三端类型同步(Three-End Type Sync)
|
||||
|
||||
### 5.1 后端导入
|
||||
|
||||
```typescript
|
||||
// server/src/services/UserService.ts
|
||||
import { User, CreateUserDTO, UpdateUserDTO } from '../shared/types';
|
||||
import { CreateUserSchema } from '../shared/schemas';
|
||||
```
|
||||
|
||||
### 5.2 前端导入
|
||||
|
||||
```typescript
|
||||
// dashboard/src/services/userDataSource.ts
|
||||
import { User, CreateUserDTO } from '@shared/types';
|
||||
// 或
|
||||
import { User } from '@/types';
|
||||
```
|
||||
|
||||
### 5.3 插件端导入
|
||||
|
||||
```typescript
|
||||
// extension/src/background/MessageHandler.ts
|
||||
import { BaseMessage, MessageResponse } from '../../server/src/shared/types';
|
||||
import { BaseMessageSchema } from '../../server/src/shared/schemas';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 类型版本管理(Type Version Management)
|
||||
|
||||
### 6.1 版本文件
|
||||
|
||||
```typescript
|
||||
// server/src/shared/types/version.ts
|
||||
export const TYPE_VERSION = '1.0.0';
|
||||
|
||||
export const TYPE_CHANGELOG: TypeChangeLog[] = [
|
||||
{
|
||||
version: '1.0.0',
|
||||
date: '2026-03-20',
|
||||
changes: [
|
||||
'Initial unified type center setup',
|
||||
'Created Zod schemas for User, Product, Order',
|
||||
'Added DTO layer with schema-driven types',
|
||||
'Added common types: Pagination, Error, Response',
|
||||
'Added plugin message types',
|
||||
'Created zodToOpenAPI converter'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export function getTypeVersion(): string {
|
||||
return TYPE_VERSION;
|
||||
}
|
||||
|
||||
export function getLatestChanges(): TypeChangeLog {
|
||||
return TYPE_CHANGELOG[0];
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 使用版本信息
|
||||
|
||||
```typescript
|
||||
import { getTypeVersion, getLatestChanges } from '@shared/types/version';
|
||||
|
||||
console.log('Type Version:', getTypeVersion());
|
||||
console.log('Latest Changes:', getLatestChanges());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. OpenAPI 文档生成(OpenAPI Documentation)
|
||||
|
||||
### 7.1 Zod 转 OpenAPI
|
||||
|
||||
```typescript
|
||||
// server/src/shared/utils/zodToOpenAPI.ts
|
||||
import { zodToOpenAPI, createAPIDocumentation } from '@shared/utils/zodToOpenAPI';
|
||||
import { CreateUserSchema, UserSchema } from '@shared/schemas';
|
||||
|
||||
const docs = createAPIDocumentation(
|
||||
'CreateUser',
|
||||
CreateUserSchema,
|
||||
UserSchema
|
||||
);
|
||||
|
||||
// docs.request → OpenAPI Schema for request
|
||||
// docs.response → OpenAPI Schema for response
|
||||
```
|
||||
|
||||
### 7.2 与 Swagger 集成
|
||||
|
||||
```typescript
|
||||
// server/src/api/routes/user.ts
|
||||
import { zodToOpenAPI } from '@shared/utils/zodToOpenAPI';
|
||||
import { CreateUserSchema } from '@shared/schemas';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /users:
|
||||
* post:
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/CreateUser'
|
||||
*/
|
||||
router.post('/users', UserController.create);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 插件消息类型(Plugin Message Types)
|
||||
|
||||
### 8.1 消息类型定义
|
||||
|
||||
```typescript
|
||||
// server/src/shared/schemas/message.schema.ts
|
||||
import { z } from 'zod';
|
||||
|
||||
export const MessageTypeSchema = z.enum([
|
||||
'COLLECT_ORDERS',
|
||||
'SYNC_ALL_ORDERS',
|
||||
'SYNC_RETURNS',
|
||||
'SYNC_ALL_RETURNS',
|
||||
'QUERY_REFUNDS',
|
||||
'AUTO_SHIP',
|
||||
'GET_SHOP_INFO',
|
||||
'UPDATE_SHOP_STATUS',
|
||||
'GET_FINGERPRINT',
|
||||
'VALIDATE_SESSION',
|
||||
'HEALTH_CHECK'
|
||||
]);
|
||||
|
||||
export const BaseMessageSchema = z.object({
|
||||
type: MessageTypeSchema,
|
||||
payload: z.record(z.string(), z.unknown()),
|
||||
traceId: z.string().optional(),
|
||||
shopId: z.string().optional(),
|
||||
platform: z.string().optional()
|
||||
});
|
||||
|
||||
export const MessageResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
data: z.unknown().optional(),
|
||||
error: z.object({
|
||||
code: z.string(),
|
||||
message: z.string()
|
||||
}).optional(),
|
||||
traceId: z.string()
|
||||
});
|
||||
```
|
||||
|
||||
### 8.2 插件端使用
|
||||
|
||||
```typescript
|
||||
// extension/src/background/MessageHandler.ts
|
||||
import { BaseMessage, MessageResponse } from '../../server/src/shared/types';
|
||||
|
||||
export class MessageHandler {
|
||||
async handle(message: BaseMessage, sender: chrome.runtime.MessageSender): Promise<MessageResponse> {
|
||||
const traceId = message.traceId || this.generateTraceId();
|
||||
|
||||
switch (message.type) {
|
||||
case 'COLLECT_ORDERS':
|
||||
return this.orderCollector.collectOrders(message.payload, traceId);
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 前端 DataSource 类型映射(Frontend DataSource Mapping)
|
||||
|
||||
### 9.1 类型映射定义
|
||||
|
||||
```typescript
|
||||
// dashboard/src/types/dataSourceMap.ts
|
||||
import type { IDataSource } from './datasource';
|
||||
import type { User, CreateUserDTO, UpdateUserDTO, UserQueryDTO } from '@shared/types';
|
||||
|
||||
export interface DataSourceMap {
|
||||
certificate: IDataSource<Certificate, CertificateQueryParams>;
|
||||
user: IDataSource<User, UserQueryDTO> & {
|
||||
create: (data: CreateUserDTO) => Promise<User>;
|
||||
update: (id: string, data: UpdateUserDTO) => Promise<User>;
|
||||
};
|
||||
product: IDataSource<Product, ProductQueryDTO>;
|
||||
order: IDataSource<Order, OrderQueryDTO>;
|
||||
}
|
||||
|
||||
export type DataSourceKey = keyof DataSourceMap;
|
||||
export type DataSourceType<K extends DataSourceKey> = DataSourceMap[K];
|
||||
```
|
||||
|
||||
### 9.2 动态获取 DataSource
|
||||
|
||||
```typescript
|
||||
export function getDataSource<K extends DataSourceKey>(key: K): DataSourceType<K> {
|
||||
const dataSources = {
|
||||
certificate: () => import('../services/certificateDataSource').then(m => m.certificateDataSource),
|
||||
user: () => import('../services/userDataSource').then(m => m.userDataSource),
|
||||
product: () => import('../services/productDataSource').then(m => m.productDataSource),
|
||||
order: () => import('../services/orderDataSource').then(m => m.orderDataSource),
|
||||
};
|
||||
|
||||
return dataSources[key]() as DataSourceType<K>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 导入规范(Import Standards)
|
||||
|
||||
### 10.1 后端导入
|
||||
|
||||
```typescript
|
||||
// ✅ 推荐:从统一类型中心导入
|
||||
import { User, Product, Order } from '../shared/types';
|
||||
import { CreateUserSchema } from '../shared/schemas';
|
||||
|
||||
// ✅ 也可以:从子模块导入
|
||||
import { User } from '../shared/types/domain';
|
||||
import { CreateUserDTO } from '../shared/types/dto';
|
||||
```
|
||||
|
||||
### 10.2 前端导入
|
||||
|
||||
```typescript
|
||||
// ✅ 推荐:使用路径别名
|
||||
import { User, Product } from '@shared/types';
|
||||
|
||||
// ✅ 兼容:从本地 types 导入
|
||||
import { User } from '@/types';
|
||||
```
|
||||
|
||||
### 10.3 插件端导入
|
||||
|
||||
```typescript
|
||||
// ✅ 推荐:使用相对路径
|
||||
import { BaseMessage, MessageResponse } from '../../server/src/shared/types';
|
||||
import { BaseMessageSchema } from '../../server/src/shared/schemas';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 开发流程(Development Workflow)
|
||||
|
||||
### 11.1 新增类型流程
|
||||
|
||||
```
|
||||
1. 定义 Zod Schema → server/src/shared/schemas/*.schema.ts
|
||||
2. 导出推导类型 → export type X = z.infer<typeof Schema>
|
||||
3. DTO 层重新导出 → server/src/shared/types/dto/*.ts
|
||||
4. Domain 层重新导出 → server/src/shared/types/domain/*.ts
|
||||
5. 更新版本号 → server/src/shared/types/version.ts
|
||||
```
|
||||
|
||||
### 11.2 修改类型流程
|
||||
|
||||
```
|
||||
1. 修改 Zod Schema
|
||||
2. 运行类型检查 → npx tsc --noEmit
|
||||
3. 修复所有类型错误
|
||||
4. 更新版本号和 CHANGELOG
|
||||
5. 提交代码
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. CI/CD 集成(CI/CD Integration)
|
||||
|
||||
### 12.1 类型检查
|
||||
|
||||
```yaml
|
||||
# .github/workflows/ci-cd.yml
|
||||
jobs:
|
||||
type-check:
|
||||
steps:
|
||||
- name: Run TypeScript check
|
||||
run: |
|
||||
cd server && npx tsc --noEmit --skipLibCheck
|
||||
cd ../dashboard && npx tsc --noEmit --skipLibCheck
|
||||
cd ../extension && npx tsc --noEmit --skipLibCheck
|
||||
```
|
||||
|
||||
### 12.2 Schema 验证
|
||||
|
||||
```yaml
|
||||
- name: Validate schemas
|
||||
run: |
|
||||
cd server && npm run test:schemas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 最佳实践(Best Practices)
|
||||
|
||||
### 13.1 DO ✅
|
||||
|
||||
- 使用 `z.infer` 从 Schema 推导类型
|
||||
- 从统一类型中心导入类型
|
||||
- 使用 Zod 进行运行时验证
|
||||
- 保持 Schema 和类型同步
|
||||
- 版本化类型变更
|
||||
|
||||
### 13.2 DON'T ❌
|
||||
|
||||
- 在各模块中重复定义类型
|
||||
- 使用 `any` 类型
|
||||
- 跳过 Zod 验证
|
||||
- 直接修改 DTO 而不更新 Schema
|
||||
- 忽略类型错误
|
||||
|
||||
---
|
||||
|
||||
## 14. 版本历史(Version History)
|
||||
|
||||
| 版本 | 描述 | 日期 |
|
||||
|------|------|------|
|
||||
| 1.0.0 | 初始版本,建立统一类型中心 | 2026-03-20 |
|
||||
|
||||
---
|
||||
|
||||
## 15. 参考资源
|
||||
|
||||
- [TypeScript 类型系统](https://www.typescriptlang.org/docs/handbook/2/types-from-types.html)
|
||||
- [zod 类型推导](https://zod.dev/?id=inferring-the-inferred-type)
|
||||
- [Schema 驱动开发](https://www.patterns.dev/posts/schema-driven-development/)
|
||||
- [OpenAPI 规范](https://swagger.io/specification/)
|
||||
Reference in New Issue
Block a user