数组类型

数组用于存储同一类型的多个元素,是开发中最常用的数据结构之一。

定义方式

方式一:类型后加 []

let numbers: number[] = [1, 2, 3, 4, 5]
let names: string[] = ["张三", "李四", "王五"]
let flags: boolean[] = [true, false, true]

方式二:泛型数组

let numbers: Array<number> = [1, 2, 3, 4, 5]
let names: Array<string> = ["张三", "李四", "王五"]

类型推断

let numbers = [1, 2, 3]           // 推断为 number[]
let names = ["张三", "李四"]       // 推断为 string[]
let mixed = [1, "hello", true]    // 推断为 (string | number | boolean)[]

常用操作

访问元素

let fruits: string[] = ["苹果", "香蕉", "橙子"]

console.log(fruits[0])      // 苹果
console.log(fruits[1])      // 香蕉
console.log(fruits.length)  // 3

添加元素

let list: number[] = [1, 2, 3]

list.push(4)          // 末尾添加
list.unshift(0)       // 开头添加

console.log(list)     // [0, 1, 2, 3, 4]

删除元素

let list: number[] = [1, 2, 3, 4, 5]

list.pop()            // 删除末尾
list.shift()          // 删除开头
list.splice(1, 1)     // 删除指定位置

console.log(list)     // [2, 4]

查找元素

let numbers: number[] = [1, 2, 3, 4, 5]

console.log(numbers.indexOf(3))      // 2
console.log(numbers.includes(3))     // true
console.log(numbers.find(n => n > 3))  // 4
console.log(numbers.findIndex(n => n > 3))  // 3

数组方法

遍历

let names: string[] = ["张三", "李四", "王五"]

names.forEach((name, index) => {
  console.log(`${index}: ${name}`)
})

for (let i = 0; i < names.length; i++) {
  console.log(names[i])
}

for (const name of names) {
  console.log(name)
}

映射

let numbers: number[] = [1, 2, 3, 4, 5]

let doubled: number[] = numbers.map(n => n * 2)
console.log(doubled)  // [2, 4, 6, 8, 10]

let users: { name: string }[] = names.map(name => ({ name }))

过滤

let numbers: number[] = [1, 2, 3, 4, 5, 6]

let evens: number[] = numbers.filter(n => n % 2 === 0)
console.log(evens)  // [2, 4, 6]

归约

let numbers: number[] = [1, 2, 3, 4, 5]

let sum: number = numbers.reduce((acc, n) => acc + n, 0)
console.log(sum)  // 15

let product: number = numbers.reduce((acc, n) => acc * n, 1)
console.log(product)  // 120

排序

let numbers: number[] = [3, 1, 4, 1, 5, 9, 2, 6]

numbers.sort((a, b) => a - b)
console.log(numbers)  // [1, 1, 2, 3, 4, 5, 6, 9]

let names: string[] = ["王五", "张三", "李四"]
names.sort()
console.log(names)  // ["张三", "李四", "王五"]

判断

let numbers: number[] = [1, 2, 3, 4, 5]

console.log(numbers.every(n => n > 0))   // true
console.log(numbers.some(n => n > 3))    // true

复杂类型数组

对象数组

interface User {
  id: number
  name: string
  age: number
}

let users: User[] = [
  { id: 1, name: "张三", age: 25 },
  { id: 2, name: "李四", age: 30 },
  { id: 3, name: "王五", age: 28 }
]

let adultNames: string[] = users
  .filter(u => u.age >= 28)
  .map(u => u.name)

console.log(adultNames)  // ["李四", "王五"]

二维数组

let matrix: number[][] = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

console.log(matrix[0][1])  // 2

只读数组

let readonlyArray: ReadonlyArray<number> = [1, 2, 3]

readonlyArray[0] = 10  // 错误
readonlyArray.push(4)  // 错误

let another: readonly number[] = [1, 2, 3]

实际应用

列表渲染

interface Product {
  id: number
  name: string
  price: number
}

function renderProducts(products: Product[]): string {
  return products
    .map(p => `${p.name}: ¥${p.price}`)
    .join("\n")
}

const products: Product[] = [
  { id: 1, name: "苹果", price: 5 },
  { id: 2, name: "香蕉", price: 3 }
]

console.log(renderProducts(products))
// 苹果: ¥5
// 香蕉: ¥3

分组

function groupBy<T>(arr: T[], key: keyof T): Record<string, T[]> {
  return arr.reduce((groups, item) => {
    const groupKey = String(item[key])
    if (!groups[groupKey]) {
      groups[groupKey] = []
    }
    groups[groupKey].push(item)
    return groups
  }, {} as Record<string, T[]>)
}

const users = [
  { name: "张三", dept: "技术部" },
  { name: "李四", dept: "市场部" },
  { name: "王五", dept: "技术部" }
]

console.log(groupBy(users, "dept"))
// { "技术部": [...], "市场部": [...] }

去重

function unique<T>(arr: T[]): T[] {
  return [...new Set(arr)]
}

console.log(unique([1, 2, 2, 3, 3, 3]))  // [1, 2, 3]

注意事项

避免使用 any[]

let bad: any[] = [1, "hello", true]  // 不推荐

let good: (string | number)[] = [1, "hello"]  // 推荐

空数组类型

let empty1: number[] = []
let empty2: never[] = []  // 只能是空数组