Skip to content

TypeScript - 数组

数组 (Arrays) 是用于存储有序项目集合的基础数据结构。在 TypeScript 中,数组被设计用于存放相同类型的项目,为数组操作提供了类型安全(type safety)。

与单独的变量相比,数组允许你在一个单一名称下高效地存储和管理多个相关值。

在 TypeScript 中,主要有两种声明数组类型的语法:

  1. 类型后跟 []: elementType[] (例如,number[], string[]) - 这是最常用的语法。
  2. 泛型数组类型 (Generic Array Type): Array<elementType> (例如,Array<number>, Array<string>) - 在某些复杂类型场景下有用。

初始化通常使用数组字面量语法 [...]。

// 使用 type[] 语法
let scores: number[] = [70, 85, 92, 68];
let names: string[] = ["Alice", "Bob", "Charlie"];
// 使用 Array<type> 语法
let flags: Array<boolean> = [true, false, true];
// 声明一个空数组(需要明确类型)
let results: number[] = [];
// 声明后初始化
let cities: string[];
cities = ["London", "Paris", "Tokyo"];
// 类型推断(Type inference)也有效
const inferredNumbers = [10, 20, 30]; // TypeScript 推断为 number[]
// inferredNumbers.push("40"); // 错误:类型 'string' 的参数不能赋给类型 'number' 的参数。

数组元素使用基于零的数字索引(zero-based numerical indices)通过方括号 [] 进行访问。

let fruits: string[] = ["Apple", "Banana", "Orange"];
console.log(fruits[0]); // 输出:Apple
console.log(fruits[1]); // 输出:Banana
// 修改一个元素
fruits[1] = "Blueberry";
console.log(fruits[1]); // 输出:Blueberry
// 访问数组长度(元素数量)
console.log(`Number of fruits: ${fruits.length}`); // 输出:3

有几种方法可以循环遍历数组元素:

直接遍历数组的值。

const colors: string[] = ["Red", "Green", "Blue"];
console.log("\nUsing for...of:"); // 使用 for...of:
for (const color of colors) {
console.log(color.toUpperCase());
}

对数组中的每个元素执行一次提供的回调函数(callback function)。

console.log("\nUsing forEach:"); // 使用 forEach:
colors.forEach((color, index) => {
console.log(`Color at index ${index}: ${color}`);
});

当你在循环体内需要访问索引时很有用。

console.log("\nUsing standard for loop:"); // 使用标准 for 循环:
for (let i = 0; i < colors.length; i++) {
console.log(`Index ${i}, Color ${colors[i]}`);
}

4. for...in 循环(通常避免用于数组)

Section titled “4. for...in 循环(通常避免用于数组)”

遍历数组的键(作为字符串的索引),包括潜在的继承属性。通常不推荐用于数组遍历;请改用 for...of 或 forEach。它更适合用于遍历对象属性。

console.log("\nUsing for...in (indices are strings):"); // 使用 for...in(索引是字符串):
for (const index in colors) {
// index 将是 "0", "1", "2"
console.log(`Index: ${index}, Type: ${typeof index}, Value: ${colors[index]}`);
}

数组拥有许多用于操作的内置方法(大部分继承自 JavaScript):

方法描述
push(item1, ...)在数组末尾添加一个或多个元素(修改原数组)。
pop()移除并返回数组的最后一个元素(修改原数组)。
shift()移除并返回数组的第一个元素(修改原数组)。
unshift(item1, ...)在数组开头添加一个或多个元素(修改原数组)。
slice(start?, end?)返回数组的一部分的浅拷贝(shallow copy)到一个新数组中(不修改原数组)。
splice(start, deleteCount?, item1?, ...)通过移除或替换现有元素和/或添加新元素来改变数组内容(修改原数组)。
concat(arr1, ...)通过将当前数组与其他数组/值合并来返回一个新数组(不修改原数组)。
join(separator?)将所有元素连接成一个字符串,由 separator 分隔(默认为 ’,’)。
indexOf(item, fromIndex?)返回给定项目在数组中第一次出现的索引,如果不存在则返回 -1。
lastIndexOf(item, fromIndex?)返回给定项目在数组中最后一次出现的索引,如果不存在则返回 -1。
includes(item, fromIndex?)如果数组包含给定项目,则返回 true,否则返回 false。
map(callbackFn)创建一个新数组,其内容是调用 callbackFn 处理数组每个元素的结果。
filter(callbackFn)创建一个新数组,其中包含所有通过 callbackFn 实现的测试的元素。
reduce(callbackFn, initialValue?)对数组中的每个元素执行一个归约函数(reducer function),最终得到一个单一输出值。
reduceRight(...)与 reduce 类似,但从右到左处理。
some(callbackFn)测试数组中是否至少有一个元素通过 callbackFn 实现的测试。
every(callbackFn)测试数组中是否所有元素都通过 callbackFn 实现的测试。
sort(compareFn?)在原数组上对元素进行排序(修改原数组)。可选的 compareFn 定义排序顺序。
reverse()在原数组上反转元素的顺序(修改原数组)。

轻松地将数组中的值分解到不同的变量中。

const coordinates: number[] = [10, 20, 30];
// 基本解构
const [x, y, z] = coordinates;
console.log(`x=${x}, y=${y}, z=${z}`); // 输出:x=10, y=20, z=30
// 带剩余元素(rest element)的解构
const [first, ...rest] = coordinates;
console.log(`First: ${first}`); // 输出:First: 10
console.log(`Rest: ${rest}`); // 输出:Rest: [20, 30]
// 跳过元素
const [, second, ] = coordinates;
console.log(`Second: ${second}`); // 输出:Second: 20

TypeScript 允许你使用 ReadonlyArray<Type> 或 readonly Type[] 创建不可变数组(immutable arrays)。这些数组创建后不能被修改。

const immutableNums: ReadonlyArray<number> = [1, 2, 3];
const readonlyStrings: readonly string[] = ["a", "b"];
// immutableNums[0] = 10; // 错误:类型 'readonly number[]' 中的索引签名只允许读取。
// immutableNums.push(4); // 错误:类型 'readonly number[]' 上不存在属性 'push'。
// 仍然可以读取元素
console.log(immutableNums[0]); // 输出:1

数组可以包含其他数组,从而创建多维结构(如矩阵或网格)。

let matrix: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(matrix[0][1]); // 输出:2(第 0 行,第 1 列)
console.log(matrix[2][0]); // 输出:7(第 2 行,第 0 列)