首页 / TypeScript 入门教程 / 数组类型

TypeScript 入门教程

数组类型

本教程共 80 篇 · 第 10 篇 · 更新于 2026-08-10 · 约 8 分钟阅读

TypeScriptTypeScript 入门教程数组ArrayReadonlyArray

本节目标:学会在 TypeScript 中声明和操作类型安全的数组,理解两种数组写法的等价性,掌握只读数组的作用,为下一章的元组做好铺垫。

数组为什么需要类型

JavaScript 的数组可以装任何东西——数字、字符串、对象混在一起都没问题。这在灵活性上是好事,但也是 bug 的来源。你本来期望 scores 数组里全是数字,结果某个地方不小心塞了个字符串,等到排序或求和时才炸。

TypeScript 的数组类型解决的就是这个问题:数组里每个元素的类型都是已知的,编译器帮你守住这条线。

let scores: number[] = [95, 88, 76, 100];
// scores.push("九十");  // ❌ 类型 "string" 不能赋给 number[]
scores.push(92);          // ✅

两种写法:T[]Array<T>

TypeScript 支持两种语法来声明数组类型:

// 写法一:T[](更常见,推荐)
let numbers: number[] = [1, 2, 3];
let names: string[] = ["小明", "小红", "小刚"];

// 写法二:Array<T>(泛型写法)
let numbers2: Array<number> = [1, 2, 3];
let names2: Array<string> = ["小明", "小红", "小刚"];

两种写法完全等价,编译结果也一样。区别在于风格偏好:number[] 更简短,在社区中更流行;Array<number> 跟其他泛型语法更统一。

Tip

日常开发中推荐用 T[],它读起来更自然——“number 数组”而不是”数字的数组”。但在需要嵌套泛型时(比如 Array<Array<number>>),Array<T> 写法更容易看清楚结构。

如果你的数组混合了不同类型,TypeScript 会推断为联合类型数组:

let mixed = [1, "hello", 3];  // 推断为 (string | number)[]

这种推断有时候不是你想要的。如果你本意是 number[] 却混入了字符串,请检查一下数据来源。

多维数组

多维数组就是”数组的数组”,类型写法是类型的嵌套:

// 二维数字数组(矩阵)
let matrix: number[][] = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

// 等价于
let matrix2: Array<Array<number>> = [
  [1, 2, 3],
  [4, 5, 6]
];

// 三维数组
let cube: number[][][] = [
  [[1, 2], [3, 4]],
  [[5, 6], [7, 8]]
];

// 访问元素
let value: number = matrix[1][2];  // 6

多维数组中每一维的类型检查都有效:

// matrix[0] = "wrong";     // ❌ string[] 不能赋给 number[]
// matrix[0][0] = "wrong";  // ❌ string 不能赋给 number

只读数组 ReadonlyArray<T>

有时候你需要保证数组不被修改——比如一个配置常量列表、一组预定义的选项。TypeScript 提供了只读数组类型:

let colors: readonly string[] = ["red", "green", "blue"];

// 所有修改操作都被禁止
// colors[0] = "yellow";      // ❌ 索引赋值不允许
// colors.push("purple");     // ❌ push 不存在于 readonly string[]
// colors.pop();              // ❌ pop 也不允许
// colors.splice(0, 1);       // ❌ splice 也不允许

// 读取操作完全正常
console.log(colors[0]);       // "red"
console.log(colors.length);   // 3
console.log(colors.includes("green"));  // true

readonly string[] 等价于 ReadonlyArray<string>

let colors2: ReadonlyArray<string> = ["red", "green", "blue"];

// colors2.push("purple");  // ❌ push 不存在

只读数组的一个关键行为:不能把只读数组赋值给可变数组。反过来也不行:

let mutable: string[] = ["a", "b"];
let readonly: readonly string[] = ["c", "d"];

// mutable = readonly;   // ❌ readonly string[] 不能赋给 string[]
readonly = mutable;      // ✅ 可变可以赋给只读

这个单向兼容设计保证了安全性——可变数组承诺”我会保持可修改”,只读数组做不到。

数组方法的类型推断

TypeScript 对数组方法的类型推断非常精准。以 mapfilter 为例:

let numbers = [1, 2, 3, 4, 5];

// map:TS 知道每个元素是 number,返回值是 number[]
let doubled = numbers.map((n) => n * 2);  // doubled: number[]

// filter:返回值仍是 number[](虽然元素变少了)
let evens = numbers.filter((n) => n % 2 === 0);  // evens: number[]

// 复杂一点的:map 返回不同类型的数组
let labels = numbers.map((n) => `第 ${n} 个`);  // labels: string[]

使用 find 时要注意返回是 T | undefined——因为可能找不到:

let numbers = [1, 2, 3, 4, 5];

let found = numbers.find((n) => n > 10);
// found 的类型是 number | undefined
// 需要检查才能安全使用

if (found !== undefined) {
  console.log(found * 2);  // ✅ 类型安全
}

数组 vs 元组:一个预告

数组和元组长得像,但语义不同:

// 数组:长度可变,所有元素同类型
let scores: number[] = [95, 88, 76];
scores.push(100);  // ✅ 可以添加

// 元组:长度固定,每个位置类型可以不同
let person: [string, number] = ["小明", 18];
// person.push(true);  // ❌ 元素类型和位置都受限

简单粗暴的区分:数组是”一堆同样的东西”,元组是”几个固定位置的东西”。下一章专门讲元组,这里先混个脸熟。

可运行示例

// 数组类型综合示例

// 1. 基本数组操作
let students: string[] = ["小明", "小红", "小刚", "小李"];
console.log(`班级共 ${students.length} 人`);

// 2. map 和 filter
let scores: number[] = [95, 88, 76, 92, 60];

let passingScores = scores.filter((s) => s >= 60);
let gradeLabels = passingScores.map((s) => {
  if (s >= 90) return "优";
  if (s >= 75) return "良";
  return "及格";
});

console.log("通过人数:", passingScores.length);
console.log("等级:", gradeLabels);

// 3. 只读数组
const DAYS: readonly string[] = ["周一", "周二", "周三", "周四", "周五"];
console.log("工作日:", DAYS.join("、"));
// DAYS.push("周六");  // ❌ 只读数组不能修改

// 4. 二维数组
let grid: number[][] = [
  [1, 2, 3],
  [4, 5, 6]
];
console.log("第二行第三列:", grid[1][2]);  // 6

输出:

班级共 4 人
通过人数: 5
等级: [ "优", "良", "良", "优", "及格" ]
工作日: 周一、周二、周三、周四、周五
第二行第三列: 6

小结

数组类型是 TypeScript 中使用频率仅次于基础类型的类型。两种写法 T[]Array<T> 效果一样,选自己顺手的。只读数组在不想让数据被意外修改时很有用。下一章我们看元组——当数组中每个位置的元素类型各不相同时,元组是最佳选择。