学习 TypeScript
请支持本书:购买捐赠
(广告,请勿屏蔽。)

2 为什么要使用 TypeScript?



如果您已经确定要学习和使用 TypeScript,则可以跳过本章。

如果您还不确定,本章就是我的推销词。

2.1 使用 TypeScript 的好处

2.1.1 更多错误可以在静态情况下检测到(无需运行代码)

在集成开发环境中编辑 TypeScript 代码时,如果输入错误的名称、调用函数不正确等,都会收到警告。

考虑以下两行代码

function func() {}
funcc();

对于第二行,我们会收到以下警告

Cannot find name 'funcc'. Did you mean 'func'?

另一个例子

const a = 0;
const b = true;
const result = a + b;

这一次,最后一行的错误消息是

Operator '+' cannot be applied to types 'number' and 'boolean'.

2.1.2 记录参数始终是一种良好的做法

记录函数和方法的参数是许多人都会做的事情

/**
 * @param {number} num - The number to convert to string
 * @returns {string} `num`, converted to string
 */
function toString(num) {
  return String(num);
}

不需要通过 {number}{string} 指定类型,但英文描述中也提到了它们。

如果我们使用 TypeScript 的符号来记录类型,我们还可以获得检查这些信息一致性的额外好处

function toString(num: number): string {
  return String(num);
}

2.1.3 TypeScript 提供了额外的文档层

每当我将 JavaScript 代码迁移到 TypeScript 时,我都会注意到一个有趣的现象:为了找到函数或方法参数的适当类型,我必须检查它在哪里被调用。这意味着静态类型在本地为我提供了我原本需要在其他地方查找的信息。

我确实发现 TypeScript 代码库比 JavaScript 代码库更容易理解:TypeScript 提供了额外的文档层。

这种额外的文档也有助于团队合作,因为它更清楚地说明了如何使用代码,并且 TypeScript 经常会在我们做错事时发出警告。

2.1.4 JavaScript 的类型定义改进了自动完成功能

如果 JavaScript 代码有类型定义,那么编辑器可以使用它们来改进自动完成功能。

使用 TypeScript 语法的另一种方法是通过 JSDoc 注释提供所有类型信息,就像我们在本章开头所做的那样。在这种情况下,TypeScript 还可以检查代码的一致性并生成类型定义。有关更多信息,请参阅 TypeScript 手册中的“类型检查 JavaScript 文件”一章

2.1.5 TypeScript 使重构更加安全

重构是许多集成开发环境提供的自动代码转换。

重命名方法是重构的一个例子。在纯 JavaScript 中这样做可能很棘手,因为相同的名称可能指的是不同的方法。TypeScript 拥有更多关于方法和类型如何连接的信息,这使得重命名方法更加安全。

2.1.6 TypeScript 可以将新功能编译成旧代码

TypeScript 倾向于快速支持 ECMAScript 第 4 阶段的功能(这些功能计划包含在下一个 ECMAScript 版本中)。当我们编译成 JavaScript 时,编译器选项 --target 允许我们指定输出兼容的 ECMAScript 版本。然后,任何不兼容的功能(在以后引入的)都将被编译成等效的、兼容的代码。

请注意,这种对旧 ECMAScript 版本的支持不需要 TypeScript 或静态类型化:JavaScript 编译器 Babel 也可以做到这一点,但它是将 JavaScript 编译成 JavaScript。

2.2 使用 TypeScript 的缺点

2.3 关于 TypeScript 的误解

2.3.1 TypeScript 代码很笨重

TypeScript 代码可能非常笨重。但它并非必须如此。例如,由于类型推断,我们通常可以只使用很少的类型注释

function selectionSort(arr: number[]) { // (A)
  for (let i=0; i<arr.length; i++) {
    const minIndex = findMinIndex(arr, i);
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; // swap
  }
}

function findMinIndex(arr: number[], startIndex: number) { // (B)
  let minValue = arr[startIndex];
  let minIndex = startIndex;
  for (let i=startIndex+1; i < arr.length; i++) {
    const curValue = arr[i];
    if (curValue < minValue) {
      minValue = curValue;
      minIndex = i;
    }
  }
  return minIndex;
}

const arr = [4, 2, 6, 3, 1, 5];
selectionSort(arr);
assert.deepEqual(
  arr, [1, 2, 3, 4, 5, 6]);

这段 TypeScript 代码与 JavaScript 代码的不同之处仅在于 A 行和 B 行。

TypeScript 有多种编写风格

2.3.2 TypeScript 试图用 C# 或 Java 替换 JavaScript

最初,TypeScript 确实发明了一些自己的语言结构(例如枚举)。但自 ECMAScript 6 以来,它主要坚持作为 JavaScript 的严格超集。

我的印象是 TypeScript 团队喜欢 JavaScript,并且不想用“更好”的东西来取代它(例如 Dart 的目标)。他们确实希望尽可能多地对 JavaScript 代码进行静态类型化。许多新的 TypeScript 功能都是由这种愿望驱动的。