# 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驱动

类型必须从 Schema（zod）推导，禁止手动定义：

```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*
