TypeScript 中的 Array(数组)详解
TypeScript 的数组类型建立在 JavaScript 数组基础上,增加了强大的静态类型检查,能确保数组元素的类型一致性,避免运行时错误。
1. 数组类型的两种声明方式(等价)
// 推荐方式:元素类型 + []
let numbers: number[] = [1, 2, 3, 4];
let names: string[] = ["Alice", "Bob"];
// 泛型方式(Array<T>)
let scores: Array<number> = [90, 85, 95];
let fruits: Array<string> = ["apple", "banana"];
推荐使用 T[] 写法,更简洁。
2. 类型推断(最常见用法)
大多数情况下无需显式标注类型,TS 会自动推断:
let list = [1, 2, 3]; // 类型推断为 number[]
let mixed = [1, "two", 3]; // 类型推断为 (number | string)[]
// 一旦推断后,类型固定
list.push("four"); // 错误:不能将 string 添加到 number[]
mixed.push(true); // 错误:boolean 不属于 number | string
3. 多维数组
// 二维数组
let matrix: number[][] = [
[1, 2],
[3, 4],
[5, 6]
];
// 三维数组
let cube: number[][][] = [[[1]]];
4. 常用数组方法(TS 提供完整类型支持)
所有标准数组方法在 TS 中都有精确的类型定义和智能提示。
| 方法 | 描述 | 返回类型 | 示例 |
|---|---|---|---|
push(...items) | 添加到末尾 | number(新长度) | arr.push(4) → 4 |
pop() | 移除并返回末尾元素 | T 或 undefined | arr.pop() → 3 |
shift() / unshift() | 头部移除/添加 | T 或 undefined / number | |
concat(...arr) | 合并数组 | 新数组 | [1,2].concat([3]) → [1,2,3] |
slice(start?, end?) | 浅拷贝子数组 | 同类型数组 | [1,2,3].slice(1) → [2,3] |
splice(start, deleteCount, ...items) | 删除/替换元素 | 被删除元素数组 | |
map<U>(callback) | 转换每个元素 | U[] | nums.map(x => x * 2) → number[] |
filter(callback) | 过滤 | 同类型数组 | nums.filter(x => x > 10) → number[] |
find(predicate) | 查找第一个匹配元素 | T 或 undefined | |
findIndex(predicate) | 查找索引 | number 或 -1 | |
some() / every() | 是否存在/全部满足 | boolean | |
reduce(callback, initial) | 归约 | 任意类型 | nums.reduce((a,b) => a+b, 0) |
forEach(callback) | 遍历,无返回值 | void | |
sort(compareFn?) | 排序(默认字符串顺序) | 同类型数组 | nums.sort((a,b) => a-b) |
TS 类型优势示例:
const names: string[] = ["bob", "alice", "charlie"];
// map 返回 string[]
const upperNames: string[] = names.map(name => name.toUpperCase());
// filter 返回 string[]
const longNames: string[] = names.filter(name => name.length > 4);
// reduce 可指定累加器类型
const totalLength: number = names.reduce((sum: number, name) => sum + name.length, 0);
5. 只读数组(ReadonlyArray)
防止数组被修改:
let readonlyNums: ReadonlyArray<number> = [1, 2, 3];
// readonlyNums.push(4); // 错误:没有 push 方法
// readonlyNums[0] = 10; // 错误:只读
// 只能使用不改变原数组的方法
let doubled: number[] = readonlyNums.map(n => n * 2);
也可以用字面量语法:
let fixed: readonly number[] = [1, 2, 3];
// fixed.push(4); // 错误
6. 元组(Tuple)—— 固定长度和类型的“数组”
元组是数组的增强版,常用于固定结构的数据。
let tuple: [string, number] = ["Alice", 30];
// tuple = ["Bob"]; // 错误:长度不足
// tuple = ["Bob", 25, true]; // 错误:长度超了
let name: string = tuple[0]; // OK
let age: number = tuple[1]; // OK
// tuple[2]; // 错误:索引越界,TS 会报错
可选元素与剩余元素(TS 4.0+):
let optionalTuple: [string, number?] = ["Bob"]; // age 可选
let restTuple: [string, ...number[]] = ["scores", 90, 85, 95];
7. 数组字面量类型
结合字面量类型限制数组内容:
type RGB = [number, number, number]; // 必须正好三个 number
let color: RGB = [255, 128, 0];
type Status = "idle" | "loading" | "success" | "error";
let states: Status[] = ["loading", "success"];
8. 最佳实践建议
| 建议 | 说明 |
|---|---|
优先使用 T[] 而非 Array<T> | 更简洁 |
| 让 TS 类型推断数组类型 | 减少冗余注解 |
使用 const 声明不变数组 | const list = [1,2,3];(内容仍可改) |
需要不可变时用 readonly T[] | 防止意外修改 |
| 多用高阶方法(map/filter/reduce) | 更函数式、更易读、更安全 |
| 元组用于固定结构数据 | 如坐标 [x, y]、返回值 [err, data] |
| 避免混合类型数组 | 除非必要(如 (string |
小结:数组类型速查
| 类型写法 | 含义 | 示例 |
|---|---|---|
number[] | 任意长度 number 数组 | [1, 2, 3] |
readonly string[] | 只读字符串数组 | as const 或显式声明 |
[string, number] | 元组(固定 2 元素) | ["Alice", 30] |
Array<boolean> | 泛型写法(同 boolean[]) | |
(string | number)[] | 联合类型数组 | [1, "two", 3] |
如果您想深入了解数组解构、泛型数组工具类型(如 Partial<T[]>)、多维数组操作或实际项目中的数组使用示例,请告诉我!