typescript-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TypeScript 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

⚠️ 不可协商的规则

  1. Type Location: ALL types MUST be in
    app/types/
    directory
    • import type { User } from '~/types/user'
    • ❌ Defining types inside components/composables
  2. Vue Components: ALWAYS use
    lang="ts"
    • <script setup lang="ts">
    • <script setup>
      without lang
  3. Function Style: ONLY arrow functions
    • const myFunc = (): string => { ... }
    • function myFunc() { ... }
  4. Return Types: ALWAYS specify return types
    • const getData = (): Promise<User[]> => { ... }
    • const getData = async () => { ... }
  5. Explicit Types: NO implicit any
    • const items: Product[] = []
    • const items = []
  6. Type Exports: ALWAYS export from
    app/types/
    • ✅ All types exported and imported
    • ❌ Local type definitions
  1. 类型存放位置:所有类型必须放在
    app/types/
    目录中
    • import type { User } from '~/types/user'
    • ❌ 在组件/组合式函数内部定义类型
  2. Vue组件:始终使用
    lang="ts"
    • <script setup lang="ts">
    • ❌ 未设置lang的
      <script setup>
  3. 函数风格:仅使用箭头函数
    • const myFunc = (): string => { ... }
    • function myFunc() { ... }
  4. 返回类型:始终指定返回类型
    • const getData = (): Promise<User[]> => { ... }
    • const getData = async () => { ... }
  5. 显式类型:禁止隐式any
    • const items: Product[] = []
    • const items = []
  6. 类型导出:始终从
    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-exports
app/
  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.ts
    ,
    product.ts
  • Use descriptive names:
    api.ts
    ,
    forms.ts
    ,
    state.ts
  • Group related types in same file
  • Export all types from each file
  • 实体类型使用单数命名:
    user.ts
    product.ts
  • 使用描述性名称:
    api.ts
    forms.ts
    state.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.ts
vue
<!-- 错误示例 -->
<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 any
Fix: 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
    app/types/
    directory
  • All Vue components use
    lang="ts"
  • All functions are arrow functions
  • All functions have explicit return types
  • No
    function
    keyword usage
  • No inline type definitions
  • No
    any
    types (use
    unknown
    if needed)
  • All variables have explicit types
  • Imports use
    import type
    for types
  • Generic types properly constrained
审查或重构TypeScript代码时,请检查:
  • 所有类型均定义在
    app/types/
    目录中
  • 所有Vue组件均使用
    lang="ts"
  • 所有函数均为箭头函数
  • 所有函数均有显式返回类型
  • 未使用
    function
    关键字
  • 无内联类型定义
  • any
    类型(必要时使用
    unknown
  • 所有变量均有显式类型
  • 使用
    import type
    导入类型
  • 泛型类型已正确约束

tsconfig Enforcement

tsconfig 强制执行

Ensure these are enabled in
tsconfig.json
:
json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true
  }
}
确保
tsconfig.json
中启用以下配置:
json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true
  }
}

Quick Reference

快速参考

✅ DO

✅ 推荐做法

  • Export all types from
    app/types/
  • Use
    lang="ts"
    in all Vue components
  • Use arrow functions exclusively
  • Specify return types on all functions
  • Use explicit types for all variables
  • Import types with
    import type
  • Use
    unknown
    instead of
    any
  • Document complex types with JSDoc
  • app/types/
    导出所有类型
  • 在所有Vue组件中使用
    lang="ts"
  • 仅使用箭头函数
  • 为所有函数指定返回类型
  • 为所有变量指定显式类型
  • 使用
    import type
    导入类型
  • 使用
    unknown
    替代
    any
  • 为复杂类型添加JSDoc注释

❌ DON'T

❌ 禁止做法

  • Define types inside components
  • Define types inside composables
  • Use
    function
    keyword
  • Omit return types
  • Use implicit
    any
  • Use
    any
    type
  • Define types in non-types files
  • Forget
    lang="ts"
    in components
  • 在组件内部定义类型
  • 在组合式函数内部定义类型
  • 使用
    function
    关键字
  • 省略返回类型
  • 使用隐式
    any
    类型
  • 使用
    any
    类型
  • 在非类型文件中定义类型
  • 忘记在组件中设置
    lang="ts"

Integration with Project

与项目的集成

This TypeScript standard works with:
  • Components:
    lang="ts"
    + external types
  • 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"
  1. Define types in
    app/types/user.ts
  2. Create component with
    lang="ts"
  3. Import types:
    import type { User } from '~/types'
  4. Use arrow functions with return types
  5. Verify all TypeScript standards followed
用户需求:"创建一个用户资料组件"
  1. app/types/user.ts
    中定义类型
  2. 创建带有
    lang="ts"
    的组件
  3. 导入类型:
    import type { User } from '~/types'
  4. 使用带返回类型的箭头函数
  5. 验证是否符合所有TypeScript标准