TypeScript 简介
对于许多通过 JavaScript 开始编程的人来说,很容易爱上它易于上手和用途广泛的特性。JavaScript 在浏览器中运行,可以在记事本中编写,逐行解释执行,不需要复杂的编译或工具。JavaScript 通过让来自各行各业的开发人员可以学习并开始编码,使软件开发民主化。但 JavaScript 的宽松性也带来了增加出错和产生错误的可能性。
考虑这个 JavaScript 程序
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 3
这是一个简单的加法程序,它被设计用来获取两个数字并将它们加在一起,返回结果。当我们用非数字的值调用这个函数时,可能会发生意想不到的、通常是不可预测的事情。
我们实际上只想用数字调用这个函数 - 否则就没有意义 - 事实上,如果您传递给它的值不是数字,您最终会得到奇怪且不可预测的结果
console.log(add(1, "2")); // 12
console.log(add(1, true)); // 2
console.log(add(1, "hello")); // 1hello
JavaScript 是一种 动态类型 语言。这意味着我们存储在变量中的数据类型可以在运行时更改。这可能会使我们难以在 JavaScript 代码中捕捉我们的意图 - 我们的 add 函数应该只用数字调用。
我们在这里看到的情况被称为 类型强制转换 - JavaScript 会自动将值从一种数据类型转换为另一种数据类型。这可以通过使用函数和运算符显式地发生,也可以通过 JavaScript 在特定上下文中期望特定类型的值而隐式地发生。隐式类型强制转换有时会导致意想不到的结果,特别是在复杂的表达式中。以下是一些情况
console.log(1 + "2"); // "12" (number 1 is converted to string)
console.log("2" + 1); // "21" (number 1 is converted to string)
console.log("5" - 1); // 4 (string "5" is converted to number)
console.log("5" * "2"); // 10 (both strings are converted to numbers)
console.log(0 == false); // true (number 0 is converted to false)
console.log(0 === false); // false (no type coercion, different types)
令人困惑,对吧?!
在 JavaScript 代码库中,我们能做的最好的事情就是在程序中添加一些保护检查,如果提供无效的值,这些检查将抛出错误。仅仅依赖这些运行时检查来保护我们免受错误的影响的问题是,我们通常会在发现代码中引入了错误时才发现错误,而用户也在同一时间发现错误。那么我们如何保护自己免受这种经常令人困惑的 JavaScript 行为呢?
TypeScript 来帮忙
TypeScript 可以通过明确我们期望在何处使用什么类型来帮助我们描述代码的意图。TypeScript 是 JavaScript 的超集,它在语言中添加了额外的类型信息。当您编译 TypeScript 时,会生成可以在任何地方运行的 JavaScript,因此您可以轻松地逐步使用它来改善您的开发体验,而无需重新构建所有软件。
类型允许您在代码运行之前捕获错误。如果您不小心将错误类型的赋值给变量,您将收到编译错误。类型还可以使您的代码更易于阅读,因为您可以明确地声明您期望的值类型。我们还可以使用工具来使类型更强大。代码编辑器和 IDE 具有内置工具,当您正确使用类型时,可以帮助您在编写代码时自动完成代码。
我们如何添加类型注释?
您可以在 TypeScript 中添加类型注释,方法是在函数参数名称后附加冒号 (:
),然后附加所需的类型。如果我们要扩展之前的 add
示例以将其转换为 TypeScript,它将如下所示
function add(x: number, y: number) {
return x + y;
}
console.log(add(1, 2)); // 3
这是我们可以对代码进行的最简单的更改,以使其更健壮。现在,编译器知道任何尝试用除两个数字以外的任何东西调用 add()
的代码都将在运行时失败,因此它将在编译时抛出错误以告诉您您的程序无效。
例如,如果我们尝试用数字和字符串调用 add,我们将收到编译错误
TypeScript 足够智能,可以根据您提供的信息为您推断程序中的一些类型,我们称之为“类型推断”。如果我们以上述示例为例并将其扩展,添加所有可能的类型注释,它将如下所示
function add(x: number, y: number): number {
return x + y;
}
const result: number = add(1, 1);
console.log(result);
在这里,我们明确地添加了函数参数的注释、add
函数的返回值类型以及变量 result
的类型。一般来说,开发人员会添加“足够的”类型注释来告诉 TypeScript 编译器正在发生的事情,并让它推断其余部分。在我们的原始示例中,通过向 x
和 y
参数添加类型注释,TypeScript 编译器可以检查代码并意识到我们只添加了两个数字,因此会推断函数返回值类型和变量 result 的类型为 number
类型。
即使您只使用 TypeScript 来注释函数参数,您也会立即从代码中消除一整类错误。
将您的 TypeScript 转换回 JavaScript
如果您的项目使用 Node 构建,您需要添加 typescript
包并运行 tsc
编译器工具。我们已经编写了 关于配置 TypeScript 编译器的介绍。
Deno 自带 TypeScript 编译器,因此如果您使用 Deno,则不需要任何其他配置或工具。 Deno 原生支持 TypeScript,会在我们执行源代码时自动将 TypeScript 转换为 JavaScript。
在客户端,您可以使用 Vite,一个我们自己喜欢的工具,它为您执行类似的透明编译,因此如果您是前端开发人员,您仍然可以在代码中获得 TypeScript 的喜悦。
下一步
在我们接下来的 Deno Bite 中,我们将讨论您在 TS 代码中需要的常见类型,以及如何使用它们来构建更复杂的类型,使您的代码清晰且无错误!