静态类型系统描述了程序运行时值的结构和行为。
像 TypeScript 这样的静态类型检查器会利用类型系统提供的信息,并在事态发展不对劲的时候告知我们。
const message = "hello!";
message();
// This expression is not callable.
// Type 'String' has no call signatures.
用 TypeScript 运行上一个例子,它会在我们执行代码之前首先抛出一个错误。
目前为止,我们讨论的都是运行时错误 —— JavaScript 运行时告诉我们,它觉得某个地方有异常。
这些异常之所以能够抛出,是因为 ECMAScript 规范 明确规定了针对异常应该表现的行为。
举个例子,规范指出,试图调用无法调用的东西应该抛出一个错误。
也许这听上去像是“显而易见的行为”,并且你会觉得,访问对象上不存在的属性时,也会抛出一个错误。
但恰恰相反,JavaScript 的表现和我们的预想不同,它返回的是值 undefined
。
const user = {
name: 'Daniel',
age: 26,
};
user.location; // 返回 undefined
最终,我们需要一个静态类型系统来告诉我们,哪些代码在这个系统中被标记为错误的代码 —— 即使它是不会马上引起错误的“有效” JavaScript 代码。
在 TypeScript 中,下面的代码会抛出一个错误,指出 location
没有定义:
const user = {
name: "Daniel",
age: 26,
};
user.location;
//Property 'location' does not exist on type '{ name: string; age: number; }'.
虽然有时候这意味着你需要在表达的内容上进行权衡,但我们的目的是为了找到程序中更多合法的 bug。
而 TypeScript 也的确可以捕获到很多合法的 bug:
举个例子,拼写错误:
const announcement = "Hello World!";
// 你需要花多久才能注意到拼写错误?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();
// 实际上正确的拼写是这样的……
announcement.toLocaleLowerCase();
未调用的函数