CLASS 01 · 2026-02-04 · 基础
静态类型是软件安全的第一道防线。本讲以冰雹数列为引例,引入类型、静态检查的概念,并阐述 6.102 对好软件的三大品质追求:免于错误、易于理解、便于修改。
我们将用一个贯穿本课的例子——冰雹数列(Hailstone sequence)——来理解静态检查的价值。规则如下:从正整数 \(n\) 开始,若 \(n\) 为偶数则下一项是 \(n/2\),若 \(n\) 为奇数则下一项是 \(3n+1\),直到数列到达 1 为止。
例如从 \(n=10\) 开始:\(10 \to 5 \to 16 \to 8 \to 4 \to 2 \to 1\),长度为 7。
类型(type)是一组值以及可在这些值上执行的运算的集合。
例如,number 是 TypeScript 中表示数字的类型,支持加减乘除等运算;string 是字符串类型,支持拼接、切片等运算。类型告诉我们一个表达式「能是什么、能做什么」。
TypeScript 是一门静态类型(statically-typed)语言。变量可以在编译时被赋予类型,由此编译器能推导出使用这些变量的表达式的类型。
// 显式类型注解:在变量名后写 :type
let n: number = 10;
let name: string = "hailstone";
// 类型不匹配会立即被编译器发现
n = "oops"; // Error: Type 'string' is not assignable to type 'number'.
编程语言发现错误的能力可以分为三个层次:
静态检查是最理想的情形——错误在萌芽阶段、尚未造成任何运行时损失时就被捕获。
function hailstoneLength(n: number): number {
let length = 1;
while (n !== 1) {
if (n % 2 === 0) {
n = n / 2;
} else {
n = 3 * n + 1;
}
length = length + 1;
}
return length;
}
// 静态检查:下面这行在编译阶段就会报错
console.log(hailstoneLength("ten"));
// ^^^^^^^^^^^^^^^ Argument of type 'string' is not assignable to parameter of type 'number'.
TypeScript 的数组是另一种类型,写法是 Array<T> 或 T[],表示「元素类型为 T 的可变长序列」。
let primes: number[] = [2, 3, 5, 7, 11];
let empty: string[] = []; // 空数组也是合法的
把一段逻辑封装成可复用的模块时,我们编写函数并附上规格注释:
/**
* 计算冰雹数列的长度。
* @param n 起始正整数 (n > 0)
* @returns 从 n 到达 1 所需的步数(含首尾)
*/
function hailstoneLength(n: number): number { /* ... */ }
这是两个常被混淆的概念:
let a: number = 5;
a = 10; // 重新赋值:a 现在指向 10
let arr: number[] = [1, 2, 3];
arr[0] = 99; // 修改:数组对象本身被改变了
为一个变量写下类型,就是在文档化你对它的假设。类型注解既是给编译器的指令,也是给未来读者(包括未来的你自己)的承诺:「这个变量始终是一个 number」。
软件工程不是「先跑起来再说」。工程师是悲观主义者:他们假设自己会犯错、假设需求会变化、假设后来者会误读代码,于是用静态类型、规格说明、测试等工具在错误造成损失之前就将其捕获。
这三大品质贯穿整个课程,也是我们做每一个工程取舍时的坐标系。
静态检查在编译时自动发现类型错误,优于运行时才发现或静默出错。
类型是一组值及其运算的集合;静态类型语言让编译器替你守住类型约定。
三大品质免于错误、易于理解、便于修改——这是 6.102 所有技术决策的出发点。