编码规范
跨项目通用编码规范基线,涵盖命名约定、不可变性、可读性(KISS/DRY/YAGNI)、错误处理及代码异味检测。覆盖 TypeScript/JavaScript、React、API 设计、文件组织、性能优化和测试标准,作为项目代码质量的共享底线,而非特定框架的详细指南。
核心定位
跨项目通用编码规范基线
作为所有项目的共享底线(shared floor),而非特定框架的详细手册。专注于命名、不可变性、可读性、错误处理等通用原则,与 frontend-patterns、backend-patterns、api-design 等专项技能互补。当需要最短可复用规则层而非完整技能走查时,优先使用 rules/common/coding-style.md。
适用场景
- 启动新项目或模块时建立规范
- 审查代码质量与可维护性
- 重构现有代码以遵循约定
- 强制执行命名、格式或结构一致性
- 配置 lint、format 或类型检查规则
- 新成员入职培训
范围边界
涵盖:描述性命名、不可变性默认、可读性(KISS/DRY/YAGNI)、错误处理期望、代码审查
不涵盖(由更专项技能负责):React 组合/hooks/渲染模式、后端架构/API 设计/数据库分层、特定框架的详细指导
四大代码质量原则
| 原则 | 核心要求 |
|---|---|
| Readability First(可读性优先) | 代码读比写多;命名清晰;自解释代码优于注释;格式一致 |
| KISS | 最简单的可行方案;避免过度工程;不 premature optimization;易懂 > 聪明 |
| DRY | 提取公共逻辑为函数;创建可复用组件;跨模块共享工具;避免复制粘贴 |
| YAGNI | 不提前构建未需要的功能;避免推测性泛化;需要时才增加复杂度;先简单后重构 |
TypeScript/JavaScript 标准
变量与函数命名
- 变量:描述性名词,如
marketSearchQuery、isUserAuthenticated、totalRevenue - 函数:动词-名词模式,如
fetchMarketData()、calculateSimilarity()、isValidEmail() - 避免:
q、flag、x等无意义缩写;仅名词的函数名如market()、email()
不可变性模式(关键)
// 推荐:始终使用展开运算符
const updatedUser = { ...user, name: 'New Name' }
const updatedArray = [...items, newItem]
// 禁止:直接修改
user.name = 'New Name' // ❌
items.push(newItem) // ❌
错误处理
- 使用
try/catch包裹异步操作 - 提供有意义的错误信息
- 在错误边界处理,不吞掉异常
Async/Await 最佳实践
// 推荐:可并行时 Promise.all
const [users, markets, stats] = await Promise.all([
fetchUsers(), fetchMarkets(), fetchStats()
])
// 禁止:不必要的串行
const users = await fetchUsers()
const markets = await fetchMarkets() // ❌
类型安全
- 使用
interface定义数据结构 - 避免
any,使用具体类型或unknown+ 类型守卫 - 函数返回值明确标注类型
React 最佳实践
组件结构
- 使用函数组件 + TypeScript Props 接口
- Props 解构并设置默认值
- 避免无类型的
props参数
自定义 Hooks
- 以
use前缀命名 - 封装可复用逻辑(如防抖、防抖、数据获取)
- 遵循 Hooks 规则(只在顶层调用)
状态管理
- 基于前状态更新时使用函数式更新:
setCount(prev => prev + 1) - 避免直接引用可能过时的状态变量
条件渲染
- 使用
&&短路运算符进行简单条件渲染 - 避免嵌套三元运算符("三元地狱")
API 设计标准
REST 约定
- URL 使用复数名词和 kebab-case
- HTTP 方法语义化:GET 获取、POST 创建、PUT/PATCH 更新、DELETE 删除
- 查询参数用于过滤、分页、排序
响应格式
// 推荐:统一结构
interface ApiResponse<T> {
success: boolean
data?: T
error?: string
meta?: { total: number; page: number; limit: number }
}
输入校验
- 使用 Schema 校验库(如 Zod)
- 校验失败返回 400 并附详细错误信息
- 区分校验错误与业务错误
文件组织
推荐目录结构
src/
├── app/ # 应用入口 / 路由
│ ├── api/ # API 路由
│ └── (auth)/ # 路由分组
├── components/ # React 组件
│ ├── ui/ # 通用 UI 组件
│ ├── forms/ # 表单组件
│ └── layouts/ # 布局组件
├── hooks/ # 自定义 Hooks
├── lib/ # 工具与配置
│ ├── api/ # API 客户端
│ ├── utils/ # 辅助函数
│ └── constants/ # 常量
├── types/ # TypeScript 类型
└── styles/ # 全局样式
文件命名
- 组件:
PascalCase(如Button.tsx) - Hooks:
camelCase以use前缀(如useAuth.ts) - 工具函数:
camelCase(如formatDate.ts) - 类型定义:
camelCase以.types后缀(如market.types.ts)
注释与文档
何时注释
- 解释 WHY 而非 WHAT
- 说明非常规选择的原因
- 复杂算法或业务逻辑的上下文
// 推荐:解释原因
// 使用指数退避避免在故障期间压垮 API
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
// 禁止:陈述显而易见的事
// 计数器加 1
count++
JSDoc 用于公共 API
@param— 参数说明@returns— 返回值说明@throws— 可能抛出的异常@example— 使用示例
性能最佳实践
Memoization
useMemo— 缓存昂贵计算useCallback— 缓存事件处理函数- 注意:
Array.prototype.sort会原地修改,需先复制
懒加载
- 使用
React.lazy+Suspense延迟加载重组件 - 路由级别代码分割
数据库查询
- 仅选择需要的列,避免
SELECT * - 使用分页限制返回数据量
测试标准
AAA 模式(Arrange-Act-Assert)
test('calculates similarity correctly', () => {
// Arrange
const vector1 = [1, 0, 0]
const vector2 = [0, 1, 0]
// Act
const similarity = calculateCosineSimilarity(vector1, vector2)
// Assert
expect(similarity).toBe(0)
})
测试命名
- 描述具体行为场景
- 包含输入、预期输出和边界条件
- 避免
test('works')、test('test search')等模糊名称
代码检测
1. 过长函数
- 限制:单个函数不超过 50 行
- 拆分:提取为更小、更专注的函数
- 每个函数只做一件事
2. 深层嵌套
- 限制:嵌套不超过 3 层
- 优化:使用提前返回替代深层 if 嵌套
// 禁止:5+ 层嵌套
if (user) { if (user.isAdmin) { if (market) { ... } } }
// 推荐:提前返回
if (!user) return
if (!user.isAdmin) return
if (!market) return
3. 魔法数字
- 禁止:未解释的数字字面量
- 推荐:使用命名常量
v1.0.0
2026-07-16
下载