TS 常用工具类型

在 TypeScript 中,常用元素类型 可以从两个维度来理解:一是基础数据类型 (Basic Types),二是复合/高级类型(Advanced Types)。下面我将系统地整理这些类型,并附上实际开发中的使用场景。

📋 基础数据类型

1. 原始类型

typescript 复制代码
// 基本类型
let isDone: boolean = false
let count: number = 42
let name: string = 'TypeScript'
let notDefined: undefined = undefined
let empty: null = null

// 特殊类型
let anything: any = '可以是任何值'  // 尽量避免使用
let unknownValue: unknown = 4       // 类型安全的 any
let nothing: void = undefined       // 函数无返回值
let neverReturns: never             // 永远不会发生的类型

2. 数组和元组

typescript 复制代码
// 数组 (Array)
let numbers: number[] = [1, 2, 3]
let strings: Array<string> = ['a', 'b', 'c']
let mixed: (string | number)[] = [1, 'two', 3]

// 元组 (Tuple) - 固定长度和类型的数组
let user: [number, string, boolean] = [1, 'Alice', true]
let httpResponse: [number, string] = [200, 'OK']

// 可选元素的元组
let optionalTuple: [string, number?] = ['hello']
optionalTuple = ['hello', 123]

// 剩余元素的元组
let restTuple: [number, ...string[]] = [1, 'a', 'b', 'c']

3. 对象类型

typescript 复制代码
// 简单对象类型
let point: { x: number; y: number } = { x: 10, y: 20 }

// 可选属性
let config: {
  url: string
  method?: 'GET' | 'POST'
  timeout?: number
} = { url: '/api' }

// 只读属性
let settings: {
  readonly id: string
  name: string
} = { id: '123', name: 'app' }
// settings.id = '456' // ❌ 错误

🎯 常用复合类型

1. 接口 (Interface)

typescript 复制代码
// 基础接口
interface User {
  id: number
  name: string
  email: string
  age?: number  // 可选属性
  readonly createdAt: Date  // 只读属性
}

// 接口继承
interface Employee extends User {
  department: string
  salary: number
}

// 接口合并(声明合并)
interface Window {
  title: string
}
interface Window {
  width: number
}
// Window 现在有 title 和 width 两个属性

2. 类型别名 (Type Alias)

typescript 复制代码
// 基本类型别名
type UserID = number | string
type Status = 'pending' | 'success' | 'error'

// 对象类型别名
type Point = {
  x: number
  y: number
}

// 联合类型
type Shape = Circle | Square | Triangle

// 交叉类型
type Draggable = { drag: () => void }
type Resizable = { resize: () => void }
type UIElement = Draggable & Resizable

// 函数类型
type Callback = (data: string) => void
type AsyncFunction<T> = () => Promise<T>

3. 函数类型

typescript 复制代码
// 函数声明
function add(x: number, y: number): number {
  return x + y
}

// 函数表达式
const multiply: (x: number, y: number) => number = (x, y) => x * y

// 函数类型别名
type MathOperation = (a: number, b: number) => number
const divide: MathOperation = (a, b) => a / b

// 可选参数和默认参数
function greet(name: string, greeting: string = 'Hello'): string {
  return `${greeting}, ${name}`
}

// 剩余参数
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, curr) => acc + curr, 0)
}

// 函数重载
function process(input: string): string[]
function process(input: number): number[]
function process(input: string | number): string[] | number[] {
  if (typeof input === 'string') {
    return input.split('')
  }
  return Array.from({ length: input }, (_, i) => i)
}

🚀 高级类型

1. 泛型 (Generics)

typescript 复制代码
// 泛型函数
function identity<T>(arg: T): T {
  return arg
}
const num = identity<number>(42)
const str = identity('hello')  // 类型推断

// 泛型接口
interface Box<T> {
  value: T
  getValue: () => T
}

// 泛型类
class Stack<T> {
  private items: T[] = []
  
  push(item: T): void {
    this.items.push(item)
  }
  
  pop(): T | undefined {
    return this.items.pop()
  }
}

// 泛型约束
interface Lengthwise {
  length: number
}
function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length)
  return arg
}

2. 联合类型 (Union Types) 和交叉类型 (Intersection Types)

typescript 复制代码
// 联合类型 - "或"
type ID = number | string
type Result = Success | Failure

// 类型守卫
function processId(id: ID): string {
  if (typeof id === 'string') {
    return id.toUpperCase()
  }
  return id.toString()
}

// 可辨识联合(Discriminated Unions)
interface Circle {
  kind: 'circle'
  radius: number
}
interface Square {
  kind: 'square'
  sideLength: number
}
type Shape = Circle | Square

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2
    case 'square':
      return shape.sideLength ** 2
  }
}

// 交叉类型 - "且"
interface Person {
  name: string
  age: number
}
interface Employee {
  company: string
  role: string
}
type Worker = Person & Employee
// Worker 同时拥有 Person 和 Employee 的所有属性

3. 类型守卫和类型断言

typescript 复制代码
// 类型守卫
function isString(value: unknown): value is string {
  return typeof value === 'string'
}

// 使用类型守卫
function process(value: string | number) {
  if (isString(value)) {
    return value.toUpperCase()  // TypeScript 知道这里是 string
  }
  return value.toFixed(2)       // TypeScript 知道这里是 number
}

// 类型断言
const canvas = document.getElementById('canvas') as HTMLCanvasElement
const input = <HTMLInputElement>document.querySelector('input')

// 非空断言
const element = document.querySelector('.exists')!
element.innerHTML = 'Hello'

// 双重断言(谨慎使用)
const expr = '42' as any as number

📦 内置工具类型

1. 常用的 Utility Types

typescript 复制代码
interface Todo {
  title: string
  description: string
  completed: boolean
  createdAt: Date
}

// Partial - 所有属性可选
type PartialTodo = Partial<Todo>
// { title?: string; description?: string; completed?: boolean; createdAt?: Date }

// Required - 所有属性必选
type RequiredTodo = Required<PartialTodo>
// 全部变成必选

// Readonly - 所有属性只读
type ReadonlyTodo = Readonly<Todo>
// 不能修改属性

// Pick - 选取指定属性
type TodoPreview = Pick<Todo, 'title' | 'completed'>
// { title: string; completed: boolean }

// Omit - 排除指定属性
type TodoWithoutDate = Omit<Todo, 'createdAt'>
// { title: string; description: string; completed: boolean }

// Record - 键值对映射
type PageInfo = Record<'home' | 'about' | 'contact', { title: string }>
// {
//   home: { title: string }
//   about: { title: string }
//   contact: { title: string }
// }

// Exclude - 从联合类型中排除
type T = Exclude<'a' | 'b' | 'c', 'a'>  // 'b' | 'c'

// Extract - 提取共有类型
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>  // 'a'

// NonNullable - 排除 null 和 undefined
type T1 = NonNullable<string | number | null | undefined>  // string | number

// ReturnType - 获取函数返回类型
function createUser() {
  return { id: 1, name: 'John' }
}
type UserType = ReturnType<typeof createUser>  // { id: number; name: string }

// Parameters - 获取函数参数类型
type CreateUserParams = Parameters<typeof createUser>  // []

2. 条件类型

typescript 复制代码
// 基础条件类型
type IsString<T> = T extends string ? true : false
type A = IsString<'hello'>  // true
type B = IsString<number>    // false

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

// infer 关键字
type UnpackPromise<T> = T extends Promise<infer U> ? U : T
type PromiseType = UnpackPromise<Promise<string>>  // string

// 内置条件类型
type NonFunction<T> = T extends Function ? never : T

🎨 实际应用场景示例

1. API 响应类型

typescript 复制代码
// API 通用响应结构
interface ApiResponse<T = any> {
  code: number
  data: T
  message: string
  timestamp: number
}

// 分页数据结构
interface PaginatedData<T> {
  items: T[]
  total: number
  page: number
  pageSize: number
  hasMore: boolean
}

// 具体业务类型
interface User {
  id: number
  name: string
  email: string
  role: 'admin' | 'user' | 'guest'
}

// 组合使用
type UserListResponse = ApiResponse<PaginatedData<User>>

2. Vue 3 组合式函数类型

typescript 复制代码
// 异步状态管理
interface AsyncState<T> {
  data: Ref<T | null>
  loading: Ref<boolean>
  error: Ref<Error | null>
  execute: () => Promise<void>
}

// 分页状态
interface PaginationState<T> {
  list: Ref<T[]>
  currentPage: Ref<number>
  pageSize: Ref<number>
  total: Ref<number>
  loading: Ref<boolean>
  loadMore: () => Promise<void>
  refresh: () => Promise<void>
}

// 表单验证
type ValidationRule<T> = {
  validator: (value: T) => boolean
  message: string
}

type FormRules<T> = {
  [K in keyof T]?: ValidationRule<T[K]>[]
}

3. 事件处理类型

typescript 复制代码
// DOM 事件
function handleClick(event: MouseEvent): void {
  console.log(event.clientX, event.clientY)
}

function handleChange(event: Event): void {
  const input = event.target as HTMLInputElement
  console.log(input.value)
}

// 自定义事件
interface CustomEvents {
  'user-login': { userId: number; timestamp: Date }
  'user-logout': { userId: number }
  'error': { message: string; code: number }
}

type EventCallback<T> = (data: T) => void

class EventEmitter {
  private events: Map<keyof CustomEvents, EventCallback<any>[]> = new Map()
  
  on<K extends keyof CustomEvents>(
    event: K,
    callback: EventCallback<CustomEvents[K]>
  ): void {
    // 实现
  }
  
  emit<K extends keyof CustomEvents>(
    event: K,
    data: CustomEvents[K]
  ): void {
    // 实现
  }
}

📌 类型定义的最佳实践

  1. 优先使用 interface 定义对象类型,特别是需要扩展的场景
  2. 使用 type 定义联合类型、交叉类型和工具类型
  3. 为所有 API 响应定义完整的类型
  4. 使用 readonly 防止意外修改
  5. 利用泛型提高代码复用性
  6. 避免使用 any,优先使用 unknown

这些是 TypeScript 中最常用和最重要的类型元素,掌握它们可以让你在日常开发中得心应手。

相关推荐
liangshanbo12157 分钟前
前端大文件切片上传怎么做?
前端
Sand(ContextGate)1 小时前
Python Agent 测试实战:测试与评估,让 Agent 像传统软件一样可交付
前端·javascript·python·microsoft·ai
广州华水科技1 小时前
单北斗GNSS变形监测系统在城市安全与地质灾害中的应用前景
前端
颜进强1 小时前
20 · NestJs循环依赖与 forwardRef:容器为什么在环面前会死,"占位再补齐"怎么救
前端·后端·ai编程
颜进强1 小时前
19 · NestJs @Global 落地账:装饰器与 `isGlobal` 参数,各在什么场景上岗
前端·后端·ai编程
码艺-Alimjan1 小时前
Tauri 网站To桌面应用实战总结
前端·javascript·vue
颜进强2 小时前
18 · NestJS动态模块与 forRoot:`imports: [ConfigModule.forRoot({...})]` 到底在 import 什么
前端·后端·ai编程
YZ1225522 小时前
【Docker专题】使用Docker部署Vue-Flask项目前后端分离版【前端Docker部署】
前端·vue.js·docker
liangshanbo12152 小时前
浏览器渲染过程:高级前端面试题
前端
太子釢2 小时前
React 函数组件与 Hook 实践指南
前端·react.js