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'.
三种检查方式
编程语言发现错误的能力可以分为三个层次:
- 静态检查(static checking):程序运行之前就自动发现错误。
- 动态检查(dynamic checking):程序执行期间自动发现错误(例如运行时抛出异常)。
- 不做检查(no checking):语言根本不帮你定位这个错误,程序可能静默地给出错误结果。
静态检查是最理想的情形——错误在萌芽阶段、尚未造成任何运行时损失时就被捕获。
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 { /* ... */ }
修改值 vs. 重新赋值
这是两个常被混淆的概念:
- 修改(mutation):改变某个值本身的内容。
- 重新赋值(reassignment):让变量指向另一个值。
let a: number = 5;
a = 10; // 重新赋值:a 现在指向 10
let arr: number[] = [1, 2, 3];
arr[0] = 99; // 修改:数组对象本身被改变了
把假设写下来
为一个变量写下类型,就是在文档化你对它的假设。类型注解既是给编译器的指令,也是给未来读者(包括未来的你自己)的承诺:「这个变量始终是一个 number」。
黑客式编程 vs. 工程
软件工程不是「先跑起来再说」。工程师是悲观主义者:他们假设自己会犯错、假设需求会变化、假设后来者会误读代码,于是用静态类型、规格说明、测试等工具在错误造成损失之前就将其捕获。
6.102 的目标:好软件的三大品质
- 免于错误(Safe from bugs):现在正确,在未来未知的情形下也保持正确。
- 易于理解(Easy to understand):与未来的程序员(包括未来的自己)清晰地沟通。
- 便于修改(Ready for change):设计时就为变化留出余地,而非每次变化都推倒重来。
这三大品质贯穿整个课程,也是我们做每一个工程取舍时的坐标系。
核心要点
静态检查在编译时自动发现类型错误,优于运行时才发现或静默出错。
类型是一组值及其运算的集合;静态类型语言让编译器替你守住类型约定。
三大品质免于错误、易于理解、便于修改——这是 6.102 所有技术决策的出发点。