typescript-best-practices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTypeScript Best Practices
TypeScript 最佳实践
Enforce project-wide TypeScript standards and conventions.
在整个项目中强制执行TypeScript标准与约定。
When to Use
适用场景
DO USE when:
- Writing any new TypeScript code
- Creating or modifying Vue components
- Defining new types or interfaces
- Creating composables or utilities
- Reviewing code for TypeScript compliance
- Refactoring JavaScript to TypeScript
- Questions about type definitions
- Type organization and structure
DO NOT USE when:
- Dealing with plain JavaScript (convert to TypeScript first)
- Configuration files that don't support TypeScript
- Third-party type definitions (use @types packages)
推荐使用场景:
- 编写任何新的TypeScript代码
- 创建或修改Vue组件
- 定义新的类型或接口
- 创建组合式函数(composables)或工具函数
- 审查代码的TypeScript合规性
- 将JavaScript重构为TypeScript
- 关于类型定义的疑问
- 类型的组织与结构设计
不推荐使用场景:
- 处理纯JavaScript代码(需先转换为TypeScript)
- 不支持TypeScript的配置文件
- 第三方类型定义(使用@types包)
Critical Standards
核心标准
⚠️ NON-NEGOTIABLE RULES
⚠️ 不可协商的规则
-
Type Location: ALL types MUST be indirectory
app/types/- ✅
import type { User } from '~/types/user' - ❌ Defining types inside components/composables
- ✅
-
Vue Components: ALWAYS use
lang="ts"- ✅
<script setup lang="ts"> - ❌ without lang
<script setup>
- ✅
-
Function Style: ONLY arrow functions
- ✅
const myFunc = (): string => { ... } - ❌
function myFunc() { ... }
- ✅
-
Return Types: ALWAYS specify return types
- ✅
const getData = (): Promise<User[]> => { ... } - ❌
const getData = async () => { ... }
- ✅
-
Explicit Types: NO implicit any
- ✅
const items: Product[] = [] - ❌
const items = []
- ✅
-
Type Exports: ALWAYS export from
app/types/- ✅ All types exported and imported
- ❌ Local type definitions
-
类型存放位置:所有类型必须放在目录中
app/types/- ✅
import type { User } from '~/types/user' - ❌ 在组件/组合式函数内部定义类型
- ✅
-
Vue组件:始终使用
lang="ts"- ✅
<script setup lang="ts"> - ❌ 未设置lang的
<script setup>
- ✅
-
函数风格:仅使用箭头函数
- ✅
const myFunc = (): string => { ... } - ❌
function myFunc() { ... }
- ✅
-
返回类型:始终指定返回类型
- ✅
const getData = (): Promise<User[]> => { ... } - ❌
const getData = async () => { ... }
- ✅
-
显式类型:禁止隐式any
- ✅
const items: Product[] = [] - ❌
const items = []
- ✅
-
类型导出:始终从导出
app/types/- ✅ 所有类型均导出并通过导入使用
- ❌ 局部类型定义
Type Organization Structure
类型组织结构
Directory Layout
目录结构
app/
types/
user.ts # User-related types
product.ts # Product types
api.ts # API response types
forms.ts # Form data types
state.ts # State management types
common.ts # Shared/utility types
errors.ts # Error types
index.ts # Optional re-exportsapp/
types/
user.ts # 用户相关类型
product.ts # 产品类型
api.ts # API响应类型
forms.ts # 表单数据类型
state.ts # 状态管理类型
common.ts # 共享/工具类型
errors.ts # 错误类型
index.ts # 可选的重新导出文件File Naming
文件命名
- Use singular for entity types: ,
user.tsproduct.ts - Use descriptive names: ,
api.ts,forms.tsstate.ts - Group related types in same file
- Export all types from each file
- 实体类型使用单数命名:、
user.tsproduct.ts - 使用描述性名称:、
api.ts、forms.tsstate.ts - 相关类型放在同一个文件中
- 从每个文件导出所有类型
Code Patterns
代码模式
Component Pattern
组件模式
typescript
// ✅ CORRECT
<script setup lang="ts">
import type { User, Product } from '~/types'
interface Props {
user: User
items: Product[]
}
const props = defineProps<Props>()
const formatName = (user: User): string => {
return `${user.firstName} ${user.lastName}`
}
</script>typescript
// ✅ 正确示例
<script setup lang="ts">
import type { User, Product } from '~/types'
interface Props {
user: User
items: Product[]
}
const props = defineProps<Props>()
const formatName = (user: User): string => {
return `${user.firstName} ${user.lastName}`
}
</script>Composable Pattern
组合式函数模式
typescript
// ✅ CORRECT
// app/composables/useData.ts
import type { User, ApiResponse } from '~/types'
export const useData = () => {
const data = ref<User | null>(null)
const fetchData = async (): Promise<User> => {
const { data: response } = await useFetch<ApiResponse<User>>('/api/user')
if (!response.value) throw new Error('No data')
return response.value.data
}
return { data, fetchData }
}typescript
// ✅ 正确示例
// app/composables/useData.ts
import type { User, ApiResponse } from '~/types'
export const useData = () => {
const data = ref<User | null>(null)
const fetchData = async (): Promise<User> => {
const { data: response } = await useFetch<ApiResponse<User>>('/api/user')
if (!response.value) throw new Error('No data')
return response.value.data
}
return { data, fetchData }
}Store Pattern
状态存储模式
typescript
// ✅ CORRECT
// app/stores/user.ts
import type { User, LoginCredentials } from '~/types'
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const login = async (creds: LoginCredentials): Promise<void> => {
// Implementation
}
return { user: readonly(user), login }
})typescript
// ✅ 正确示例
// app/stores/user.ts
import type { User, LoginCredentials } from '~/types'
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const login = async (creds: LoginCredentials): Promise<void> => {
// 实现逻辑
}
return { user: readonly(user), login }
})Utility Pattern
工具函数模式
typescript
// ✅ CORRECT
// app/utils/formatters.ts
import type { User, Product } from '~/types'
export const formatUser = (user: User): string => {
return `${user.firstName} ${user.lastName}`
}
export const calculateTotal = (products: Product[]): number => {
return products.reduce((sum: number, p: Product): number =>
sum + p.price, 0
)
}typescript
// ✅ 正确示例
// app/utils/formatters.ts
import type { User, Product } from '~/types'
export const formatUser = (user: User): string => {
return `${user.firstName} ${user.lastName}`
}
export const calculateTotal = (products: Product[]): number => {
return products.reduce((sum: number, p: Product): number =>
sum + p.price, 0
)
}Type Definition Patterns
类型定义模式
Basic Entity Types
基础实体类型
typescript
// app/types/user.ts
export interface User {
id: string
email: string
firstName: string
lastName: string
role: UserRole
createdAt: Date
}
export type UserRole = 'admin' | 'user' | 'guest'typescript
// app/types/user.ts
export interface User {
id: string
email: string
firstName: string
lastName: string
role: UserRole
createdAt: Date
}
export type UserRole = 'admin' | 'user' | 'guest'API Response Types
API响应类型
typescript
// app/types/api.ts
export interface ApiResponse<T> {
data: T
message: string
success: boolean
}
export interface PaginatedResponse<T> {
items: T[]
total: number
page: number
}typescript
// app/types/api.ts
export interface ApiResponse<T> {
data: T
message: string
success: boolean
}
export interface PaginatedResponse<T> {
items: T[]
total: number
page: number
}Form Types
表单类型
typescript
// app/types/forms.ts
export interface LoginForm {
email: string
password: string
}
export interface FormField<T> {
value: T
error: string | null
touched: boolean
}typescript
// app/types/forms.ts
export interface LoginForm {
email: string
password: string
}
export interface FormField<T> {
value: T
error: string | null
touched: boolean
}State Types
状态类型
typescript
// app/types/state.ts
export interface LoadingState {
isLoading: boolean
error: Error | null
}
export interface DataState<T> extends LoadingState {
data: T | null
}typescript
// app/types/state.ts
export interface LoadingState {
isLoading: boolean
error: Error | null
}
export interface DataState<T> extends LoadingState {
data: T | null
}Common Violations & Fixes
常见违规与修复方案
❌ Inline Type Definition
❌ 内联类型定义
vue
<!-- WRONG -->
<script setup lang="ts">
interface User { // ❌ Type defined inline
id: string
name: string
}
</script>Fix: Move to
app/types/user.tsvue
<!-- 错误示例 -->
<script setup lang="ts">
interface User { // ❌ 类型定义在内部
id: string
name: string
}
</script>修复方案:将类型移至
app/types/user.ts❌ Missing Return Type
❌ 缺少返回类型
typescript
// WRONG
const getData = async () => { // ❌ No return type
return data
}Fix: Add explicit return type
typescript
// CORRECT
const getData = async (): Promise<Data> => {
return data
}typescript
// 错误示例
const getData = async () => { // ❌ 未指定返回类型
return data
}修复方案:添加显式返回类型
typescript
// 正确示例
const getData = async (): Promise<Data> => {
return data
}❌ Function Keyword
❌ 使用function关键字
typescript
// WRONG
function handleClick() { // ❌ function keyword
// ...
}Fix: Use arrow function
typescript
// CORRECT
const handleClick = (): void => {
// ...
}typescript
// 错误示例
function handleClick() { // ❌ 使用function关键字
// ...
}修复方案:使用箭头函数
typescript
// 正确示例
const handleClick = (): void => {
// ...
}❌ Missing lang="ts"
❌ 缺少lang="ts"
vue
<!-- WRONG -->
<script setup> <!-- ❌ No lang="ts" -->
const data = ref()
</script>Fix: Add lang="ts"
vue
<!-- CORRECT -->
<script setup lang="ts">
const data = ref<string>('')
</script>vue
<!-- 错误示例 -->
<script setup> <!-- ❌ 未设置lang="ts" -->
const data = ref()
</script>修复方案:添加lang="ts"
vue
<!-- 正确示例 -->
<script setup lang="ts">
const data = ref<string>('')
</script>❌ Implicit Any
❌ 隐式any类型
typescript
// WRONG
const items = [] // ❌ Implicit any[]
const user = ref() // ❌ Implicit anyFix: Add explicit types
typescript
// CORRECT
const items: string[] = []
const user = ref<User | null>(null)typescript
// 错误示例
const items = [] // ❌ 隐式any[]类型
const user = ref() // ❌ 隐式any类型修复方案:添加显式类型
typescript
// 正确示例
const items: string[] = []
const user = ref<User | null>(null)Refactoring Checklist
重构检查清单
When reviewing or refactoring TypeScript code:
- All types defined in directory
app/types/ - All Vue components use
lang="ts" - All functions are arrow functions
- All functions have explicit return types
- No keyword usage
function - No inline type definitions
- No types (use
anyif needed)unknown - All variables have explicit types
- Imports use for types
import type - Generic types properly constrained
审查或重构TypeScript代码时,请检查:
- 所有类型均定义在目录中
app/types/ - 所有Vue组件均使用
lang="ts" - 所有函数均为箭头函数
- 所有函数均有显式返回类型
- 未使用关键字
function - 无内联类型定义
- 无类型(必要时使用
any)unknown - 所有变量均有显式类型
- 使用导入类型
import type - 泛型类型已正确约束
tsconfig Enforcement
tsconfig 强制执行
Ensure these are enabled in :
tsconfig.jsonjson
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true
}
}确保中启用以下配置:
tsconfig.jsonjson
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true
}
}Quick Reference
快速参考
✅ DO
✅ 推荐做法
- Export all types from
app/types/ - Use in all Vue components
lang="ts" - Use arrow functions exclusively
- Specify return types on all functions
- Use explicit types for all variables
- Import types with
import type - Use instead of
unknownany - Document complex types with JSDoc
- 从导出所有类型
app/types/ - 在所有Vue组件中使用
lang="ts" - 仅使用箭头函数
- 为所有函数指定返回类型
- 为所有变量指定显式类型
- 使用导入类型
import type - 使用替代
unknownany - 为复杂类型添加JSDoc注释
❌ DON'T
❌ 禁止做法
- Define types inside components
- Define types inside composables
- Use keyword
function - Omit return types
- Use implicit
any - Use type
any - Define types in non-types files
- Forget in components
lang="ts"
- 在组件内部定义类型
- 在组合式函数内部定义类型
- 使用关键字
function - 省略返回类型
- 使用隐式类型
any - 使用类型
any - 在非类型文件中定义类型
- 忘记在组件中设置
lang="ts"
Integration with Project
与项目的集成
This TypeScript standard works with:
- Components: + external types
lang="ts" - Composables: Arrow functions + return types
- Stores: Pinia with typed state/actions
- Utils: Pure functions with explicit types
- API: Typed requests/responses
本TypeScript标准适用于:
- 组件:+ 外部类型
lang="ts" - 组合式函数:箭头函数 + 返回类型
- 状态存储:带类型化状态/动作的Pinia
- 工具函数:带显式类型的纯函数
- API:类型化的请求/响应
Additional Resources
额外资源
Example Workflow
示例工作流程
User: "Create a user profile component"
- Define types in
app/types/user.ts - Create component with
lang="ts" - Import types:
import type { User } from '~/types' - Use arrow functions with return types
- Verify all TypeScript standards followed
用户需求:"创建一个用户资料组件"
- 在中定义类型
app/types/user.ts - 创建带有的组件
lang="ts" - 导入类型:
import type { User } from '~/types' - 使用带返回类型的箭头函数
- 验证是否符合所有TypeScript标准