2025-01-20 · 4 min read

TypeScript 实用技巧和最佳实践

#typescript#programming#best-practices

前言

TypeScript 已经成为现代 JavaScript 开发的标准选择。它不仅提供了类型安全,还带来了更好的开发体验和代码可维护性。本文将分享一些实用的 TypeScript 技巧和最佳实践。

类型推断和类型注解

让 TypeScript 推断类型

typescript
// ✅ 好的做法:让 TypeScript 推断类型
const users = ['Alice', 'Bob', 'Charlie']

// ❌ 不必要的类型注解
const users: string[] = ['Alice', 'Bob', 'Charlie']

使用 const 断言

typescript
// 普通数组
const colors = ['red', 'green', 'blue'] // string[]

// 使用 as const
const colors = ['red', 'green', 'blue'] as const // readonly ["red", "green", "blue"]

// 对象字面量
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
} as const

实用工具类型

Partial 和 Required

typescript
interface User {
  name: string
  email: string
  age: number
}

// 所有属性变为可选
type PartialUser = Partial<User>
// { name?: string; email?: string; age?: number }

// 所有属性变为必需
type RequiredUser = Required<PartialUser>

Pick 和 Omit

typescript
interface User {
  id: number
  name: string
  email: string
  password: string
}

// 选择特定属性
type PublicUser = Pick<User, 'id' | 'name' | 'email'>

// 排除特定属性
type UserWithoutPassword = Omit<User, 'password'>

Record 类型

typescript
// 创建键值对类型
type Status = 'pending' | 'approved' | 'rejected'
type StatusConfig = Record<Status, { color: string; message: string }>

const config: StatusConfig = {
  pending: { color: 'yellow', message: '等待审核' },
  approved: { color: 'green', message: '已通过' },
  rejected: { color: 'red', message: '已拒绝' },
}

函数类型

函数重载

typescript
function format(value: string): string
function format(value: number): string
function format(value: boolean): string
function format(value: string | number | boolean): string {
  return String(value)
}

泛型函数

typescript
// 简单的泛型函数
function identity<T>(arg: T): T {
  return arg
}

// 带约束的泛型
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}

const user = { name: 'Alice', age: 30 }
const name = getProperty(user, 'name') // string
const age = getProperty(user, 'age') // number

类型守卫

typescript
// 类型守卫函数
function isString(value: unknown): value is string {
  return typeof value === 'string'
}

function processValue(value: unknown) {
  if (isString(value)) {
    // TypeScript 知道 value 是 string
    console.log(value.toUpperCase())
  }
}

// 自定义类型守卫
interface Cat {
  type: 'cat'
  meow: () => void
}

interface Dog {
  type: 'dog'
  bark: () => void
}

function isCat(animal: Cat | Dog): animal is Cat {
  return animal.type === 'cat'
}

条件类型

typescript
// 基础条件类型
type NonNullable<T> = T extends null | undefined ? never : T

// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never
type StrArrOrNumArr = ToArray<string | number> // string[] | number[]

// 实用示例:提取 Promise 类型
type Awaited<T> = T extends Promise<infer U> ? U : T

模板字面量类型

typescript
type EventName<T extends string> = `on${Capitalize<T>}`
type ClickEvent = EventName<'click'> // 'onClick'
type ChangeEvent = EventName<'change'> // 'onChange'

// 结合联合类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'
type ApiEndpoint = `/api/${string}`
type ApiRoute = `${HttpMethod} ${ApiEndpoint}`

错误处理

typescript
// Result 类型模式
type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E }

function divide(a: number, b: number): Result<number> {
  if (b === 0) {
    return { success: false, error: new Error('Division by zero') }
  }
  return { success: true, data: a / b }
}

// 使用
const result = divide(10, 2)
if (result.success) {
  console.log(result.data) // TypeScript 知道 data 存在
} else {
  console.error(result.error) // TypeScript 知道 error 存在
}

最佳实践

  1. 避免使用 any:使用 unknown 代替
  2. 启用严格模式strict: true 在 tsconfig.json
  3. 使用类型而不是接口:对于联合类型和交叉类型
  4. 利用类型推断:不要过度注解类型
  5. 使用 const 断言:获得更精确的类型

总结

TypeScript 提供了强大的类型系统,合理使用这些技巧可以显著提升代码质量和开发效率。记住,类型系统是你的朋友,让它帮助你写出更好的代码!

Getting Started with Next.js 15使用 Contentlayer 构建现代化博客