面向新程序员的 TypeScript

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

¥Congratulations on choosing TypeScript as one of your first languages — you’re already making good decisions!

你可能已经听说 TypeScript 是 JavaScript 的 “香料” 或 “变体”。TypeScript (TS) 和 JavaScript (JS) 之间的关系在现代编程语言中相当独特,因此更多地了解这种关系将有助于你了解 TypeScript 如何添加到 JavaScript 中。

¥You’ve probably already heard that TypeScript is a “flavor” or “variant” of JavaScript. The relationship between TypeScript (TS) and JavaScript (JS) is rather unique among modern programming languages, so learning more about this relationship will help you understand how TypeScript adds to JavaScript.

什么是 JavaScript?简短的历史

¥What is JavaScript? A Brief History

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

¥JavaScript (also known as ECMAScript) started its life as a simple scripting language for browsers. At the time it was invented, it was expected to be used for short snippets of code embedded in a web page — writing more than a few dozen lines of code would have been somewhat unusual. Due to this, early web browsers executed such code pretty slowly. Over time, though, JS became more and more popular, and web developers started using it to create interactive experiences.

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

¥Web browser developers responded to this increased JS usage by optimizing their execution engines (dynamic compilation) and extending what could be done with it (adding APIs), which in turn made web developers use it even more. On modern websites, your browser is frequently running applications that span hundreds of thousands of lines of code. This is the long and gradual growth of “the web”, starting as a simple network of static pages, and evolving into a platform for rich applications of all kinds.

不仅如此,JS 已经变得足够流行,可以在浏览器上下文之外使用,例如使用 node.js 实现 JS 服务器。JS 的 “随处运行” 特性使其成为跨平台开发的有吸引力的选择。现在有很多开发者只使用 JavaScript 来编写他们的整个堆栈!

¥More than this, JS has become popular enough to be used outside the context of browsers, such as implementing JS servers using node.js. The “run anywhere” nature of JS makes it an attractive choice for cross-platform development. There are many developers these days that use only JavaScript to program their entire stack!

总而言之,我们拥有一种专为快速使用而设计的语言,然后发展成为一种成熟的工具来编写具有数百万行的应用。每种语言都有自己的怪癖 - 奇怪和惊喜,而 JavaScript 的卑微起步使其拥有许多这样的怪癖。一些例子:

¥To summarize, we have a language that was designed for quick uses, and then grew to a full-fledged tool to write applications with millions of lines. Every language has its own quirks — oddities and surprises, and JavaScript’s humble beginning makes it have many of these. Some examples:

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

    ¥JavaScript’s equality operator (==) coerces its operands, leading to unexpected behavior:

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

    ¥JavaScript also allows accessing properties which aren’t present:

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

当发生此类错误时,大多数编程语言都会抛出错误,有些语言会在编译期间(在任何代码运行之前)抛出错误。在编写小程序时,这种怪癖很烦人但可以管理;在编写包含数百或数千行代码的应用时,这些不断出现的意外是一个严重的问题。

¥Most programming languages would throw an error when these sorts of errors occur, some would do so during compilation — before any code is running. When writing small programs, such quirks are annoying but manageable; when writing applications with hundreds or thousands of lines of code, these constant surprises are a serious problem.

TypeScript:静态类型检查器

¥TypeScript: A Static Type Checker

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

¥We said earlier that some languages wouldn’t allow those buggy programs to run at all. Detecting errors in code without running it is referred to as static checking. Determining what’s an error and what’s not based on the kinds of values being operated on is known as static type checking.

TypeScript 在执行前检查程序是否有错误,并根据值的种类进行检查,使其成为静态类型检查器。例如,上面的最后一个例子因为 obj 的类型而出错。这是 TypeScript 发现的错误:

¥TypeScript checks a program for errors before execution, and does so based on the kinds of values, making it a static type checker. For example, the last example above has an error because of the type of obj. Here’s the error TypeScript found:

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 超集

¥A Typed Superset of JavaScript

但是,TypeScript 与 JavaScript 有何关系?

¥How does TypeScript relate to JavaScript, though?

语法

¥Syntax

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

¥TypeScript is a language that is a superset of JavaScript: JS syntax is therefore legal TS. Syntax refers to the way we write text to form a program. For example, this code has a syntax error because it’s missing a ):

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

由于其语法,TypeScript 不会将任何 JavaScript 代码视为错误。这意味着你可以将任何有效的 JavaScript 代码放入 TypeScript 文件中,而不必担心它的具体编写方式。

¥TypeScript doesn’t consider any JavaScript code to be an error because of its syntax. This means you can take any working JavaScript code and put it in a TypeScript file without worrying about exactly how it is written.

类型

¥Types

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

¥However, TypeScript is a typed superset, meaning that it adds rules about how different kinds of values can be used. The earlier error about obj.heigth was not a syntax error: it is an error of using some kind of value (a type) in an incorrect way.

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

¥As another example, this is JavaScript code that you can run in your browser, and it will log a value:

js
console.log(4 / []);

这个语法上合法的程序记录了 Infinity。但是,TypeScript 将数字除以数组视为无意义的操作,并且会触发错误:

¥This syntactically-legal program logs Infinity. TypeScript, though, considers division of number by an array to be a nonsensical operation, and will issue an error:

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 检查代码的严格程度的设置。)

¥It’s possible you really did intend to divide a number by an array, perhaps just to see what happens, but most of the time, though, this is a programming mistake. TypeScript’s type checker is designed to allow correct programs through while still catching as many common errors as possible. (Later, we’ll learn about settings you can use to configure how strictly TypeScript checks your code.)

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

¥If you move some code from a JavaScript file to a TypeScript file, you might see type errors depending on how the code is written. These may be legitimate problems with the code, or TypeScript being overly conservative. Throughout this guide we’ll demonstrate how to add various TypeScript syntax to eliminate such errors.

运行时行为

¥Runtime Behavior

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

¥TypeScript is also a programming language that preserves the runtime behavior of JavaScript. For example, dividing by zero in JavaScript produces Infinity instead of throwing a runtime exception. As a principle, TypeScript never changes the runtime behavior of JavaScript code.

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

¥This means that if you move code from JavaScript to TypeScript, it is guaranteed to run the same way, even if TypeScript thinks that the code has type errors.

保持与 JavaScript 相同的运行时行为是 TypeScript 的基本保证,因为这意味着你可以轻松地在两种语言之间转换,而不必担心可能导致程序停止运行的细微差异。

¥Keeping the same runtime behavior as JavaScript is a foundational promise of TypeScript because it means you can easily transition between the two languages without worrying about subtle differences that might make your program stop working.

擦除的类型

¥Erased Types

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

¥Roughly speaking, once TypeScript’s compiler is done with checking your code, it erases the types to produce the resulting “compiled” code. This means that once your code is compiled, the resulting plain JS code has no type information.

这也意味着 TypeScript 永远不会根据它推断的类型更改程序的行为。最重要的是,虽然你可能会在编译期间看到类型错误,但类型系统本身与程序运行时的工作方式无关。

¥This also means that TypeScript never changes the behavior of your program based on the types it inferred. The bottom line is that while you might see type errors during compilation, the type system itself has no bearing on how your program works when it runs.

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

¥Finally, TypeScript doesn’t provide any additional runtime libraries. Your programs will use the same standard library (or external libraries) as JavaScript programs, so there’s no additional TypeScript-specific framework to learn.

学习 JavaScript 和 TypeScript

¥Learning JavaScript and TypeScript

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

¥We frequently see the question “Should I learn JavaScript or TypeScript?“.

答案是不学 JavaScript 就学不会 TypeScript!TypeScript 与 JavaScript 共享语法和运行时行为,因此你学习的任何有关 JavaScript 的知识都可以同时帮助你学习 TypeScript。

¥The answer is that you can’t learn TypeScript without learning JavaScript! TypeScript shares syntax and runtime behavior with JavaScript, so anything you learn about JavaScript is helping you learn TypeScript at the same time.

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

¥There are many, many resources available for programmers to learn JavaScript; you should not ignore these resources if you’re writing TypeScript. For example, there are about 20 times more StackOverflow questions tagged javascript than typescript, but all of the javascript questions also apply to TypeScript.

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

¥If you find yourself searching for something like “how to sort a list in TypeScript”, remember: TypeScript is JavaScript’s runtime with a compile-time type checker. The way you sort a list in TypeScript is the same way you do so in JavaScript. If you find a resource that uses TypeScript directly, that’s great too, but don’t limit yourself to thinking you need TypeScript-specific answers for everyday questions about how to accomplish runtime tasks.

下一步

¥Next Steps

这是对日常 TypeScript 中使用的语法和工具的简要概述。从这里,你可以:

¥This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can: