面向新程序员的 TypeScript

恭喜你选择 TypeScript 作为你的第一语言之一——你已经做出了正确的决定!

你可能已经听说 TypeScript 是 JavaScript (JS) 的“风格”或“变体”。TypeScript (TS) 和 JavaScript (JS) 之间的关系在现代编程语言中是独一无二的,因此更多地了解这种关系将帮助你理解 TypeScript 如何添加到 JavaScript 中。

什么是 JavaScript?简史

JavaScript(也称为 ECMAScript)最初是一种简单的浏览器脚本语言。在发明之初,它被期望用于嵌入在网页中的短代码片段——编写几十行以上的代码会有些不同寻常。因此,早期的网络浏览器执行此类代码的速度非常慢。然而,随着时间的推移,JS 变得越来越流行,网络开发者开始使用它创建交互式体验。

网络浏览器开发者通过优化其执行引擎(动态编译)和扩展其功能(添加 API)来应对 JS 使用量的增加,这反过来又让网络开发者更多地使用它。在现代网站上,你的浏览器经常运行跨越数十万行代码的应用程序。这是“网络”漫长而渐进的增长,它从一个简单的静态页面网络开始,演变成一个适用于各种丰富应用程序的平台。

更重要的是,JS 已变得足够流行,可以在浏览器环境之外使用,例如使用 node.js 实现 JS 服务器。“随处运行”的 JS 特性使其成为跨平台开发的理想选择。如今,许多开发者使用 JavaScript 来编程他们的整个堆栈!

总之,我们有一种专为快速使用而设计的语言,然后发展成为一种编写数百万行应用程序的成熟工具。每种语言都有其自身的怪癖——奇异之处和意外之处,而 JavaScript 的卑微开端使其拥有许多这样的怪癖。一些示例

  • JavaScript 的相等运算符 (==) 强制转换其操作数,导致意外的行为

    js
    if ("" == 0) {
    // It is! But why??
    }
    if (1 < x < 3) {
    // True for *any* value of x!
    }
  • JavaScript 还允许访问不存在的属性

    js
    const obj = { width: 10, height: 15 };
    // Why is this NaN? Spelling is hard!
    const area = obj.width * obj.heigth;

大多数编程语言会在出现此类错误时抛出错误,有些会在编译期间(在任何代码运行之前)这样做。在编写小型程序时,此类怪癖令人讨厌但可控;在编写包含数百或数千行代码的应用程序时,这些持续的意外是一个严重的问题。

TypeScript:静态类型检查器

我们之前说过,有些语言根本不允许那些有缺陷的程序运行。在不运行代码的情况下检测代码中的错误被称为静态检查。根据被操作的值的类型来确定什么是错误,什么是正确的被称为静态类型检查。

TypeScript 在执行之前检查程序中的错误,并且根据值的类型进行检查,使其成为一个静态类型检查器。例如,上面的最后一个示例由于 obj类型而存在错误。以下是 TypeScript 发现的错误

ts
const obj = { width: 10, height: 15 };
const area = obj.width * obj.heigth;
Property 'heigth' does not exist on type '{ width: number; height: number; }'. Did you mean 'height'?2551Property 'heigth' does not exist on type '{ width: number; height: number; }'. Did you mean 'height'?
Try

JavaScript 的类型化超集

那么 TypeScript 与 JavaScript 有什么关系呢?

语法

TypeScript 是一种语言,是 JavaScript 的超集:因此 JS 语法是合法的 TS。语法是指我们编写文本以形成程序的方式。例如,此代码存在语法错误,因为它缺少 )

ts
let a = (4
')' expected.1005')' expected.
Try

TypeScript 不会因为语法而将任何 JavaScript 代码视为错误。这意味着你可以获取任何可用的 JavaScript 代码并将其放入 TypeScript 文件中,而无需担心它的具体编写方式。

类型

然而,TypeScript 是一个类型化超集,这意味着它添加了有关如何使用不同类型的值的规则。有关 obj.heigth 的早期错误不是语法错误:它是以不正确的方式使用某种值(类型)的错误。

作为另一个示例,这是可以在浏览器中运行的 JavaScript 代码,它记录一个值

js
console.log(4 / []);

这个语法合法的程序记录了 Infinity。然而,TypeScript 认为数字除以数组是一个无意义的操作,并将发出一个错误

ts
console.log(4 / []);
The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.2363The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
Try

你可能确实打算将一个数字除以一个数组,也许只是想看看会发生什么,但大多数情况下,这是一个编程错误。TypeScript 的类型检查器旨在允许正确的程序通过,同时尽可能多地捕获常见错误。(稍后,我们将了解可用于配置 TypeScript 如何严格检查代码的设置。)

如果你将一些代码从 JavaScript 文件移动到 TypeScript 文件,你可能会看到类型错误,具体取决于代码的编写方式。这些可能是代码的合法问题,或者 TypeScript 过于保守。在整个指南中,我们将演示如何添加各种 TypeScript 语法以消除此类错误。

运行时行为

TypeScript 也是一种保留 JavaScript 的运行时行为的编程语言。例如,在 JavaScript 中除以零会产生 Infinity,而不是抛出运行时异常。作为一个原则,TypeScript 从不改变 JavaScript 代码的运行时行为。

这意味着,如果你将代码从 JavaScript 移动到 TypeScript,它保证以相同的方式运行,即使 TypeScript 认为代码有类型错误。

与 JavaScript 保持相同的运行时行为是 TypeScript 的基本承诺,因为它意味着你可以在两种语言之间轻松转换,而不用担心可能使你的程序停止工作的细微差别。

已擦除的类型

粗略地说,一旦 TypeScript 的编译器完成对代码的检查,它就会擦除类型以生成结果“已编译”的代码。这意味着一旦编译代码,生成的纯 JS 代码就没有类型信息。

这也意味着 TypeScript 永远不会根据它推断的类型来更改程序的行为。底线是,虽然您可能会在编译期间看到类型错误,但类型系统本身对程序在运行时的工作方式没有影响。

最后,TypeScript 不提供任何其他运行时库。您的程序将使用与 JavaScript 程序相同的标准库(或外部库),因此无需学习其他 TypeScript 特定的框架。

学习 JavaScript 和 TypeScript

我们经常看到这样的问题:“我应该学习 JavaScript 还是 TypeScript?”。

答案是,不学习 JavaScript 就无法学习 TypeScript!TypeScript 与 JavaScript 共享语法和运行时行为,因此您学习 JavaScript 的任何内容同时也在帮助您学习 TypeScript。

有很多资源可供程序员学习 JavaScript;如果您正在编写 TypeScript,则不应忽略这些资源。例如,标记为javascript的 StackOverflow 问题比标记为typescript的问题多大约 20 倍,但所有javascript问题也适用于 TypeScript。

如果您发现自己正在搜索“如何在 TypeScript 中对列表进行排序”之类的内容,请记住:TypeScript 是具有编译时类型检查器的 JavaScript 运行时。您在 TypeScript 中对列表进行排序的方式与在 JavaScript 中进行排序的方式相同。如果您找到直接使用 TypeScript 的资源,那也很棒,但不要局限于认为您需要 TypeScript 特定的答案来回答有关如何完成运行时任务的日常问题。

下一步

这是 TypeScript 日常使用语法和工具的简介。从这里,你可以

TypeScript 文档是一个开源项目。通过发送拉取请求,帮助我们改进这些页面

此页面贡献者
OTOrta Therox (19)
EBEli Barzilay (2)
XLXavi Lee (1)
NSNick Schonning (1)
AOAlex Ownejazayeri (1)
8+

上次更新:2024 年 3 月 21 日