Files
makemd/docs/RULES/typescript.md

257 lines
4.4 KiB
Markdown
Raw Normal View History

# TypeScript规则
> **入口**: [_index.md](_index.md)
---
## 1. 核心原则
### 1.1 禁止any
```typescript
// ❌ 禁止
function process(data: any) { ... }
const result: any = fetchData();
// ✅ 正确
function process(data: unknown) {
if (typeof data === 'string') {
// 类型收窄后使用
}
}
interface FetchResult {
id: string;
name: string;
}
const result: FetchResult = fetchData();
```
### 1.2 函数必须声明返回类型
```typescript
// ❌ 禁止
function getProduct(id: string) {
return db('cf_product').where({ id }).first();
}
// ✅ 正确
interface Product {
id: string;
name: string;
price: number;
}
async function getProduct(id: string): Promise<Product | null> {
return db('cf_product').where({ id }).first();
}
```
### 1.3 API必须定义类型
```typescript
// ❌ 禁止
router.post('/api/v1/products', async (ctx) => {
const body = ctx.request.body; // any
// ...
});
// ✅ 正确
interface CreateProductRequest {
name: string;
price: number;
platform: string;
}
interface CreateProductResponse {
success: boolean;
data: Product;
}
router.post('/api/v1/products', async (ctx) => {
const body = ctx.request.body as CreateProductRequest;
// ...
});
```
---
## 2. 类型定义规范
### 2.1 Schema驱动
类型必须从 Schemazod推导禁止手动定义
```typescript
// ❌ 禁止:手动定义类型
interface Product {
id: string;
name: string;
price: number;
}
// ✅ 正确从Schema推导
import { z } from 'zod';
const ProductSchema = z.object({
id: z.string(),
name: z.string(),
price: z.number(),
});
type Product = z.infer<typeof ProductSchema>;
```
### 2.2 统一类型中心
所有类型只从 `/types` 目录导入:
```typescript
// ❌ 禁止:各模块重复定义
// services/ProductService.ts
interface Product { ... }
// ✅ 正确:从类型中心导入
import { Product, CreateProductRequest } from '@/types';
```
### 2.3 类型边界分层
```
API 返回数据 → Schema 验证 → DTO 转换 → Domain 模型
```
```typescript
// 1. API返回不可信
const apiData = await fetchProduct();
// 2. Schema验证
const validated = ProductSchema.parse(apiData);
// 3. DTO转换
const dto: ProductDTO = {
id: validated.id,
name: validated.name,
price: validated.price,
};
// 4. Domain模型
const domain: Product = Product.fromDTO(dto);
```
---
## 3. 编译检查
### 3.1 强制规则
| 规则 | 说明 |
|------|------|
| 编译错误 = 构建失败 | TypeScript 编译错误必须阻断 CI/CD |
| 提交前检查 | 必须通过 `tsc --noEmit` 检查 |
| ESLint 强制 | 必须通过 `@typescript-eslint` 规则检查 |
### 3.2 禁止行为
```typescript
// ❌ 禁止:忽略错误
// @ts-ignore
const result = someFunction();
// ❌ 禁止:禁用检查
// @ts-nocheck
function process() { ... }
// ❌ 禁止将类型改为any来"解决"错误
const data: any = fetchData();
```
---
## 4. 类型转换
### 4.1 类型守卫
```typescript
// ✅ 正确:使用类型守卫
function isProduct(data: unknown): data is Product {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'name' in data &&
'price' in data
);
}
function process(data: unknown) {
if (isProduct(data)) {
// data 类型为 Product
console.log(data.name);
}
}
```
### 4.2 类型断言
```typescript
// ❌ 禁止:过度使用断言
const product = data as Product;
// ✅ 正确先用Schema验证
const product = ProductSchema.parse(data);
```
---
## 5. 文件规模限制
| 类型 | 限制 |
|------|------|
| 单文件 | ≤ 1500 行 |
| 单函数 | ≤ 120 行 |
| UI组件 | ≤ 300 行 |
---
## 6. 命名规范
### 6.1 文件命名
| 类型 | 格式 | 示例 |
|------|------|------|
| 组件 | PascalCase | `ProductList.tsx` |
| 服务 | PascalCase | `ProductService.ts` |
| 工具 | camelCase | `formatPrice.ts` |
| 类型 | camelCase | `productTypes.ts` |
### 6.2 类型命名
```typescript
// 接口:不加 I 前缀
interface Product { ... }
// 类型别名:描述性名称
type ProductStatus = 'ACTIVE' | 'INACTIVE';
// 泛型:单字母或描述性名称
function getItems<T>(): T[] { ... }
function transform<Input, Output>(data: Input): Output { ... }
```
---
## 7. 检查命令
```bash
# 类型检查
npx tsc --noEmit
# 检查错误数量
npx tsc --noEmit 2>&1 | Select-String -Pattern "^src/" | Measure-Object
```
---
*最后更新: 2026-03-22*