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 中最常用和最重要的类型元素,掌握它们可以让你在日常开发中得心应手。

相关推荐
WebInfra几秒前
Rspack 2.3 发布:联手 SWC 团队带来全新编译器
前端·javascript·github
德尔塔A17 分钟前
中文全文检索加向量,我用 SQLite 做到零依赖
typescript
wflynn27 分钟前
GitHub 今日推荐|rea:用 MCP 把反编译器和 AI agent 接到一起的逆向工具
typescript·开源·github·agent·agent-skills·binary-analysis
德尔塔A28 分钟前
AI 改了 300KB 的文件,我让浏览器一屏都不多拿
typescript
德尔塔A35 分钟前
给 Agent 写终端界面,我一个 UI 库都没装
typescript
德尔塔A36 分钟前
同一条命令,在 Windows 上炸了三种方式
typescript
小卿噢1 小时前
同样是插 10 万行,最快的写法比最慢的快 103 倍
前端
德尔塔A1 小时前
同一个会话,终端和浏览器同时开着会发生什么
typescript
weixin_417396831 小时前
星级酒店境外电视频道怎么合法接入?合规要点与核对清单
开发语言·前端·php·1024程序员节·综合布线
hiahiahia1231 小时前
Structured Output
前端·人工智能