面向新程序员的 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)最初是作为浏览器的简单脚本语言诞生的。
在它被发明的时候,人们预期它主要用于嵌入网页的一小段代码——写超过几十行代码是比较不寻常的。
因此,早期的网页浏览器执行这类代码的速度相当慢。
然而,随着时间的推移,JavaScript 变得越来越受欢迎,网页开发者开始使用它来创建交互式体验。

🌐 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.

网页浏览器开发者针对 JavaScript 使用量的增加,通过优化其执行引擎(动态编译)和扩展其功能(添加 API)作出了回应,这反过来又使网页开发者使用它的频率更高。在现代网站上,你的浏览器经常运行的应用代码可能多达数十万行。这就是“网络”的长期、渐进式增长历程——从最初的静态页面网络,发展到如今成为各种丰富_应用_的平台。

🌐 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 的相等运算符(==)会对其操作数进行 类型转换,从而导致意外行为:

    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;

大多数编程语言在发生这类错误时会抛出错误,有些会在编译期间就出现——在任何代码运行之前。
在编写小程序时,这些怪癖虽然烦人,但可控;而在编写几百或几千行代码的应用时,这些不断出现的意外就成为了一个严重的问题。

🌐 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: