命名规范
本章定义 TypeScript 项目的命名规范,确保代码的一致性和可读性。
标识符命名
1.1 变量和函数命名
1.1.1 基本规则
typescript
// ✅ 普通变量和函数:camelCase
const userName = 'John'
const isActive = true
let currentIndex = 0
function calculateTotal(price: number, tax: number): number {
return price + tax
}
const getUserById = (id: string) => {
// 实现
}
// ✅ 常量:UPPER_SNAKE_CASE
const MAX_RETRY_COUNT = 3
const API_BASE_URL = 'https://api.example.com'
const DEFAULT_PAGE_SIZE = 20
// ✅ 对象常量:对象本身大写,属性用 PascalCase
const Status = {
Active: 'active',
Inactive: 'inactive',
Pending: 'pending'
} as const
const HttpMethod = {
Get: 'GET',
Post: 'POST',
Put: 'PUT',
Delete: 'DELETE'
} as const
1.1.2 布尔变量命名
typescript
// ✅ 使用 is/has/can/should/will 前缀
const isLoading = true
const hasPermission = user.role === 'admin'
const canEdit = hasPermission && !isLoading
const shouldUpdate = isDirty && isValid
const willDelete = confirmDialog.result === 'yes'
// ✅ 函数返回布尔值也使用相同规则
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}
function hasAccess(user: User, resource: Resource): boolean {
return user.permissions.includes(resource.requiredPermission)
}
// ❌ 避免:模糊的布尔名称
const flag = true // 不清晰
const active = true // 应该是 isActive
const permission = false // 应该是 hasPermission
1.1.3 数组和集合命名
typescript
// ✅ 使用复数形式
const users: User[] = []
const activeUserIds: string[] = []
const permissions = new Set<Permission>()
const userRoles = new Map<string, Role[]>()
// ✅ 或者使用 xxxList/xxxArray 后缀(当复数形式不明显时)
const childList: Node[] = []
const dataArray: number[] = []
// ❌ 避免:单数形式表示集合
const user: User[] = [] // 应该是 users
const child: Node[] = [] // 应该是 children 或 childList
1.2 类、接口和类型命名
1.2.1 PascalCase 规则
typescript
// ✅ 类:PascalCase,不加前缀
class UserService {
// 实现
}
class HttpClient {
// 实现
}
// ✅ 接口:PascalCase,不加 I 前缀
interface User {
id: string
name: string
email: string
}
interface ApiResponse<T> {
data: T
status: number
message: string
}
// ✅ 类型别名:PascalCase,不加 T 前缀
type UserId = string
type UserRole = 'admin' | 'user' | 'guest'
type AsyncCallback<T> = (error: Error | null, data?: T) => void
// ❌ 避免:匈牙利命名法
interface IUser { } // 不要加 I 前缀
type TResponse = { } // 不要加 T 前缀
class CUserService { } // 不要加 C 前缀
1.2.2 泛型参数命名
typescript
// ✅ 简单泛型:单字母
function identity<T>(value: T): T {
return value
}
function map<T, U>(array: T[], fn: (item: T) => U): U[] {
return array.map(fn)
}
// ✅ 复杂泛型:描述性命名
interface ApiResponse<TData, TError = Error> {
data?: TData
error?: TError
loading: boolean
}
type EventHandler<TEvent extends Event = Event> = (event: TEvent) => void
class Repository<TEntity extends BaseEntity, TId = string> {
// 实现
}
// ✅ 常用泛型参数命名约定
// T - Type(类型)
// K - Key(键)
// V - Value(值)
// E - Element(元素)或 Error(错误)
// TData - 数据类型
// TResult - 结果类型
// TResponse - 响应类型
// TRequest - 请求类型
1.3 私有成员命名
1.3.1 类成员命名
typescript
// ✅ 私有成员无特殊标记,依赖 private 关键字
class UserService {
private cache: Map<string, User>
private readonly config: Config
public async getUser(id: string): Promise<User> {
return this.fetchUser(id)
}
private async fetchUser(id: string): Promise<User> {
// 实现
}
}
// ✅ 使用 ES2022 私有字段(如果目标环境支持)
class ModernService {
#cache: Map<string, any>
#config: Config
constructor(config: Config) {
this.#config = config
this.#cache = new Map()
}
private clearCache(): void {
this.#cache.clear()
}
}
// ❌ 避免:下划线前缀(过时的做法)
class OldService {
private _cache: Map<string, any> // 不推荐
private _fetchData(): void { } // 不推荐
}
文件和目录命名
2.1 文件命名规则
2.1.1 根据内容决定命名风格
bash
# ✅ 单一结构(类/接口/类型/组件):PascalCase
UserService.ts # export class UserService
UserProfile.ts # export interface UserProfile
ApiResponse.ts # export type ApiResponse
Button.tsx # export function Button() - React 组件
UserCard.vue # export default defineComponent() - Vue 组件
# ✅ 工具集合(多个函数/常量):kebab-case
string-utils.ts # 多个字符串工具函数
date-helpers.ts # 多个日期辅助函数
api-endpoints.ts # API 端点常量集合
validation-rules.ts # 验证规则集合
http-client.ts # HTTP 客户端工具
# ✅ 特殊文件:固定命名
index.ts # 模块入口
index.test.ts # 测试文件
index.spec.ts # 规格测试
setupTests.ts # 测试配置
2.1.2 文件命名示例
typescript
// UserService.ts - 单一类导出
export class UserService {
// 类实现
}
// UserProfile.ts - 单一接口导出
export interface UserProfile {
id: string
name: string
// ...
}
// string-utils.ts - 多个工具函数
export function capitalize(str: string): string { }
export function truncate(str: string, length: number): string { }
export function slugify(str: string): string { }
// constants.ts - 常量集合
export const API_VERSION = 'v1'
export const MAX_FILE_SIZE = 10 * 1024 * 1024
export const SUPPORTED_FORMATS = ['jpg', 'png', 'gif']
2.1.3 测试文件命名
bash
# ✅ 测试文件与源文件保持一致的命名风格
UserService.ts # 源文件
UserService.test.ts # 对应的测试文件
string-utils.ts # 源文件
string-utils.test.ts # 对应的测试文件
# ✅ 或者放在 __tests__ 目录
src/
UserService.ts
__tests__/
UserService.test.ts
2.2 目录命名规则
2.2.1 目录始终使用 kebab-case
bash
src/
├── components/ # 组件目录
├── services/ # 服务目录
├── utils/ # 工具目录
├── types/ # 类型定义
├── api-clients/ # API 客户端
├── user-management/ # 用户管理模块
└── payment-gateway/ # 支付网关模块
2.2.2 模块目录结构
bash
# ✅ 功能模块的标准结构
user-management/
├── index.ts # 模块导出
├── UserService.ts # 服务类
├── UserRepository.ts # 仓储类
├── UserProfile.ts # 类型定义
├── user-utils.ts # 工具函数
└── constants.ts # 模块常量
特殊命名约定
3.1 React/Vue 组件命名
3.1.1 组件命名规则
typescript
// ✅ React 组件:PascalCase
// UserCard.tsx
export function UserCard({ user }: UserCardProps) {
return <div>{user.name}</div>
}
// ✅ Vue 组件:PascalCase
// UserCard.vue
export default defineComponent({
name: 'UserCard' // 组件名也是 PascalCase
})
// ✅ 组件属性接口:组件名 + Props
interface UserCardProps {
user: User
onClick?: () => void
}
interface ButtonProps {
variant: 'primary' | 'secondary'
disabled?: boolean
}
// ✅ 组件事件处理器:handle + 事件名
interface FormProps {
onSubmit: (data: FormData) => void
onChange: (field: string, value: any) => void
}
function Form({ onSubmit, onChange }: FormProps) {
const handleSubmit = (e: FormEvent) => {
e.preventDefault()
onSubmit(data)
}
const handleFieldChange = (field: string) => (value: any) => {
onChange(field, value)
}
}
3.2 事件和回调命名
3.2.1 事件处理器命名
typescript
// ✅ 事件处理器:handle + 名词 + 动词
const handleButtonClick = () => { }
const handleFormSubmit = () => { }
const handleInputChange = () => { }
const handleUserDelete = () => { }
// ✅ 事件属性:on + 名词 + 动词
interface ComponentProps {
onClick?: () => void
onSubmit?: (data: any) => void
onChange?: (value: string) => void
onUserSelect?: (user: User) => void
}
// ✅ 事件发射器:emit + 事件名
class EventBus {
emitUserLogin(user: User) { }
emitDataUpdate(data: any) { }
emitErrorOccurred(error: Error) { }
}
3.3 异步操作命名
3.3.1 异步函数命名
typescript
// ✅ 异步操作:动词 + 名词
async function fetchUser(id: string): Promise<User> { }
async function loadSettings(): Promise<Settings> { }
async function saveProfile(profile: Profile): Promise<void> { }
async function deleteComment(id: string): Promise<boolean> { }
// ✅ Promise 相关变量
const userPromise = fetchUser(userId)
const loadingPromise = loadData()
// ✅ 加载状态变量
const isLoading = true
const isFetching = false
const isSaving = false
const isDeleting = false
常见问题
缩写词如何处理?
typescript
// ✅ 缩写词在 PascalCase 中只首字母大写
class HttpApi { } // 不是 HTTPApi
class XmlParser { } // 不是 XMLParser
interface JsonData { } // 不是 JSONData
// ✅ 缩写词在 camelCase 中全部小写
const apiUrl = '' // 不是 apiURL
const xmlData = '' // 不是 xMLData
function parseJson() { } // 不是 parseJSON
// ✅ 常量中缩写词全部大写
const API_URL = ''
const MAX_HTTP_RETRIES = 3
数字如何处理?
typescript
// ✅ 数字可以出现在名称中
const h1Element = document.querySelector('h1')
const base64Encode = (str: string) => { }
const sha256Hash = (data: Buffer) => { }
// ❌ 避免:数字开头(语法错误)
// const 1stItem = '' // 错误
// function 2ndPhase() { } // 错误
特殊字符和 Unicode?
typescript
// ✅ 只使用 ASCII 字母、数字和 $、_
const userName = 'John'
const $element = document.querySelector('.app')
const _privateHelper = () => { } // 虽然合法但不推荐
// ❌ 避免:Unicode 字符
const 用户名 = 'John' // 不推荐
const naïve = true // 不推荐
最佳实践
DO ✅
- 保持命名一致性
- 使用描述性名称
- 遵循团队约定
- 布尔值使用 is/has/can 前缀
- 文件名反映其主要导出
- 常量使用 UPPER_SNAKE_CASE
- 类型相关使用 PascalCase
DON'T ❌
- 不要使用匈牙利命名法(I 前缀、T 前缀)
- 避免使用下划线前缀表示私有
- 不要使用拼音命名
- 避免过度缩写
- 不要在类型中使用 any 作为名称的一部分
- 避免使用保留字作为名称
- 不要使用单字母变量(除了循环索引和泛型参数)
下一步
掌握命名规范后,请参考: