Skip to content

TypeScript 高级技巧与实战

TypeScript 作为 JavaScript 的超集,提供了强大的类型系统和丰富的高级特性。本文将深入探讨一些实用的高级技巧,帮助你写出更优雅、更安全的代码。

1. 高级类型操作

条件类型(Conditional Types)

条件类型允许我们根据类型条件来选择不同的类型:

typescript
type NonNullable<T> = T extends null | undefined ? never : T

// 实用示例:API 响应类型处理
type ApiResponse<T> = T extends string
  ? { message: T }
  : T extends object
  ? { data: T }
  : { value: T }

type StringResponse = ApiResponse<string> // { message: string }
type ObjectResponse = ApiResponse<{ id: number }> // { data: { id: number } }

映射类型(Mapped Types)

映射类型可以基于现有类型创建新类型:

typescript
// 深度只读
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

// 可选属性转必需
type RequiredKeys<T, K extends keyof T> = T & Required<Pick<T, K>>

interface User {
  id?: number
  name?: string
  email?: string
}

type UserWithRequiredEmail = RequiredKeys<User, 'email'>
// { id?: number; name?: string; email: string }

2. 模板字面量类型

模板字面量类型提供了强大的字符串操作能力:

typescript
// 事件名称生成
type EventName<T extends string> = `on${Capitalize<T>}`
type ClickEvent = EventName<'click'> // 'onClick'

// 路由类型安全
type Route = '/users' | '/posts' | '/settings'
type ApiEndpoint<T extends Route> = `https://api.example.com${T}`

type UserEndpoint = ApiEndpoint<'/users'> // 'https://api.example.com/users'

// CSS 属性类型
type CSSProperty = 'margin' | 'padding' | 'border'
type CSSDirection = 'top' | 'right' | 'bottom' | 'left'
type CSSPropertyWithDirection = `${CSSProperty}-${CSSDirection}`
// 'margin-top' | 'margin-right' | ... | 'border-left'

3. 高级泛型技巧

泛型约束与推断

typescript
// 键值对提取
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  const result = {} as Pick<T, K>
  keys.forEach(key => {
    result[key] = obj[key]
  })
  return result
}

// 函数参数推断
type Parameters<T extends (...args: any) => any> = T extends (
  ...args: infer P
) => any
  ? P
  : never

type ReturnType<T extends (...args: any) => any> = T extends (
  ...args: any
) => infer R
  ? R
  : any

// 实用示例
function createApiClient<T extends Record<string, (...args: any[]) => any>>(
  endpoints: T
): {
  [K in keyof T]: (
    ...args: Parameters<T[K]>
  ) => Promise<ReturnType<T[K]>>
} {
  // 实现省略
  return {} as any
}

4. 类型守卫与断言

自定义类型守卫

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

function isNumber(value: unknown): value is number {
  return typeof value === 'number' && !isNaN(value)
}

// 对象类型守卫
interface User {
  id: number
  name: string
  email: string
}

function isUser(obj: unknown): obj is User {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'id' in obj &&
    'name' in obj &&
    'email' in obj &&
    typeof (obj as User).id === 'number' &&
    typeof (obj as User).name === 'string' &&
    typeof (obj as User).email === 'string'
  )
}

// 泛型类型守卫
function hasProperty<T, K extends PropertyKey>(
  obj: T,
  key: K
): obj is T & Record<K, unknown> {
  return typeof obj === 'object' && obj !== null && key in obj
}

5. 装饰器与元数据

类装饰器

typescript
// 日志装饰器
function Logger<T extends { new (...args: any[]): {} }>(constructor: T) {
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args)
      console.log(`Creating instance of ${constructor.name}`)
    }
  }
}

// 方法装饰器
function Measure(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value
  
  descriptor.value = function (...args: any[]) {
    const start = performance.now()
    const result = originalMethod.apply(this, args)
    const end = performance.now()
    console.log(`${propertyKey} took ${end - start} milliseconds`)
    return result
  }
}

@Logger
class ApiService {
  @Measure
  async fetchData(url: string): Promise<any> {
    // 实现省略
    return fetch(url).then(res => res.json())
  }
}

6. 实战应用场景

状态管理类型安全

typescript
// Redux 风格的状态管理
interface AppState {
  user: User | null
  posts: Post[]
  loading: boolean
}

type ActionType = 'SET_USER' | 'SET_POSTS' | 'SET_LOADING'

interface Action<T extends ActionType, P = any> {
  type: T
  payload: P
}

type SetUserAction = Action<'SET_USER', User | null>
type SetPostsAction = Action<'SET_POSTS', Post[]>
type SetLoadingAction = Action<'SET_LOADING', boolean>

type AppAction = SetUserAction | SetPostsAction | SetLoadingAction

// 类型安全的 reducer
function appReducer(state: AppState, action: AppAction): AppState {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload } // payload 自动推断为 User | null
    case 'SET_POSTS':
      return { ...state, posts: action.payload } // payload 自动推断为 Post[]
    case 'SET_LOADING':
      return { ...state, loading: action.payload } // payload 自动推断为 boolean
    default:
      return state
  }
}

API 客户端类型安全

typescript
// API 端点定义
interface ApiEndpoints {
  '/users': {
    GET: { response: User[] }
    POST: { body: Omit<User, 'id'>; response: User }
  }
  '/users/:id': {
    GET: { params: { id: string }; response: User }
    PUT: { params: { id: string }; body: Partial<User>; response: User }
    DELETE: { params: { id: string }; response: void }
  }
}

// 类型安全的 API 客户端
class TypedApiClient {
  async request<
    Path extends keyof ApiEndpoints,
    Method extends keyof ApiEndpoints[Path]
  >(
    path: Path,
    method: Method,
    options?: ApiEndpoints[Path][Method] extends { params: infer P }
      ? { params: P } & (ApiEndpoints[Path][Method] extends { body: infer B }
          ? { body: B }
          : {})
      : ApiEndpoints[Path][Method] extends { body: infer B }
      ? { body: B }
      : {}
  ): Promise<
    ApiEndpoints[Path][Method] extends { response: infer R } ? R : never
  > {
    // 实现省略
    return {} as any
  }
}

// 使用示例
const api = new TypedApiClient()

// 类型安全的 API 调用
const users = await api.request('/users', 'GET') // 返回 User[]
const user = await api.request('/users/:id', 'GET', { params: { id: '1' } }) // 返回 User
const newUser = await api.request('/users', 'POST', {
  body: { name: 'John', email: 'john@example.com' }
}) // 返回 User

7. 性能优化技巧

类型计算优化

typescript
// 避免深度递归类型
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]
}

// 使用分布式条件类型
type Flatten<T> = T extends (infer U)[] ? U : T

// 缓存复杂类型计算
type CachedComplexType<T> = T extends string
  ? StringResult
  : T extends number
  ? NumberResult
  : DefaultResult

interface StringResult { type: 'string' }
interface NumberResult { type: 'number' }
interface DefaultResult { type: 'default' }

总结

TypeScript 的高级特性为我们提供了强大的类型安全保障和开发体验。通过合理使用这些技巧,我们可以:

  1. 提高代码质量:通过类型系统捕获潜在错误
  2. 增强开发体验:获得更好的 IDE 支持和自动补全
  3. 改善代码维护性:类型作为文档,提高代码可读性
  4. 优化性能:编译时类型检查,运行时零开销

掌握这些高级技巧,将让你在 TypeScript 开发中更加得心应手,写出更加优雅和安全的代码。

相关文章

用代码构建未来,让技术改变世界 🚀 | 专注前端技术,分享开发经验