什么是TypeScript,为什么我会用它来代替JavaScript?[已关闭]TypeScript 与 JavaScript 的关系TypeScript与其他JavaScript目标语言的关系(可选)静态类型和类型推断增强的 IDE 支持严格的空检查汇编JavaScript 互操作性Converting from JavaScript to TypeScriptAdoption

2022-08-29 21:55:34

你能描述一下TypeScript语言是什么吗?

它能做什么,JavaScript或可用的库不能做什么,这将使我有理由考虑它?


答案 1

我最初写这个答案的时候,TypeScript还很热。五年后,这是一个不错的概述,但看看下面的Lodewijk的答案以获得更深入的了解

1000英尺视图...

TypeScript是JavaScript的超集,它主要提供可选的静态类型,类和接口。其中一大好处是使 IDE 能够提供更丰富的环境,以便在键入代码时发现常见错误。

要了解我的意思,请观看Microsoft关于该语言的介绍性视频

对于大型JavaScript项目,采用TypeScript可能会产生更强大的软件,同时仍然可以在常规JavaScript应用程序运行的地方部署。

它是开源的,但只有在使用受支持的IDE时,您才能在键入时获得聪明的智能感知。最初,这只是微软的Visual Studio(在Miguel de Icaza的博客文章中也有说明)。如今,其他IDE也提供TypeScript支持

还有其他类似的技术吗?

CoffeeScript,但这确实有不同的目的。恕我直言,CoffeeScript为人类提供了可读性,但TypeScript也通过其可选的静态类型为工具提供了深度可读性(请参阅最近的博客文章以获取更多批评)。还有Dart,但这是JavaScript的完整替代品(尽管它可以生成JavaScript代码。)

例如,这里有一些TypeScript(你可以在TypeScript Playground中玩这个))

class Greeter {
    greeting: string;
    constructor (message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}  

这是它将产生的JavaScript。

var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();

请注意 TypeScript 如何定义成员变量和类方法参数的类型。这在转换为 JavaScript 时会被删除,但 IDE 和编译器会使用它来发现错误,例如将数值类型传递给构造函数。

它还能够推断出未显式声明的类型,例如,它将确定该方法返回字符串。greet()

调试 TypeScript

许多浏览器和 IDE 通过源代码映射提供直接调试支持。有关更多详细信息,请参阅此堆栈溢出问题:使用 Visual Studio 调试 TypeScript 代码

想知道更多吗?

我最初写这个答案的时候,TypeScript还很热。查看Lodewijk对此问题的回答,以获取更多最新细节。


答案 2

TypeScript 与 JavaScript 的关系

TypeScript是JavaScript的类型化超集,可编译为普通的JavaScript - typescriptlang.org

JavaScript是由ECMA技术委员会39开发的一种编程语言,该委员会是由许多不同的利益相关者组成的一群人。TC39 是由 ECMA(一个内部标准组织)主持的委员会。JavaScript有许多不同的实现,由许多不同的供应商(例如Google,Microsoft,Oracle等)实现。JavaScript的目标是成为网络的通用语言。

TypeScript是JavaScript语言的超集,它具有单个开源编译器,主要由单个供应商开发:Microsoft。TypeScript的目标是通过类型系统帮助早期发现错误,并使JavaScript开发更加高效。

从本质上讲,TypeScript通过三种方式实现其目标:

  1. 支持现代 JavaScript 功能 - JavaScript 语言(不是运行时)通过 ECMAScript 标准进行标准化。并非所有浏览器和 JavaScript 运行时都支持所有 ECMAScript 标准的所有功能(请参阅此概述)。TypeScript 允许使用许多最新的 ECMAScript 功能,并将它们转换为您选择的较旧的 ECMAScript 目标(请参阅编译器选项下的编译目标列表)。这意味着您可以安全地使用新功能,如模块,lambda函数,类,spread运算符和解构,同时保持与旧浏览器和JavaScript运行时的向后兼容。--target

  2. 高级类型系统 - 类型支持不是 ECMAScript 标准的一部分,并且可能永远不会是由于 JavaScript 的解释性质而不是编译性质。TypeScript的类型系统非常丰富,包括:接口,枚举,混合类型,泛型,联合/交集类型,访问修饰符等等。TypeScript的官方网站概述了这些功能。Typescript的类型系统与大多数其他类型化语言相当,在某些情况下可以说更强大。

  3. 开发人员工具支持 - TypeScript 的编译器可以作为后台进程运行,以支持增量编译和 IDE 集成,以便您可以更轻松地导航、识别问题、检查可能性和重构代码库。

TypeScript与其他JavaScript目标语言的关系

与编译为JavaScript的其他语言相比,TypeScript具有独特的理念。JavaScript代码是有效的TypeScript代码;TypeScript 是 JavaScript 的超集。您几乎可以将文件重命名为文件并开始使用TypeScript(请参阅下面的“JavaScript互操作性”)。TypeScript文件被编译为可读的JavaScript,因此可以迁移回去,并且理解编译的TypeScript并不难。TypeScript建立在JavaScript的成功之上,同时改进了它的弱点。.js.ts

一方面,你有未来的证明工具,这些工具采用现代的ECMAScript标准,并将其编译成较旧的JavaScript版本,其中Babel是最受欢迎的版本。另一方面,你的语言可能与面向JavaScript的JavaScript完全不同,比如CoffeeScript,Clojure,Dart,Elm,Haxe,Scala.js,以及更多的主机(见这个列表)。这些语言,虽然它们可能比JavaScript的未来更好,但冒着更大的风险,没有找到足够的采用来保证它们的未来。您可能也很难找到其中一些语言的有经验的开发人员,尽管您会发现这些语言通常更热情。与JavaScript的互操作性也可能更加复杂,因为它们与JavaScript的实际内容相去甚远。

TypeScript介于这两个极端之间,从而平衡了风险。从任何标准来看,TypeScript都不是一个有风险的选择。如果您熟悉JavaScript,则只需很少的努力就可以习惯,因为它不是一种完全不同的语言,具有出色的JavaScript互操作性支持,并且最近已经看到了很多采用。

(可选)静态类型和类型推断

JavaScript 是动态类型的。这意味着JavaScript不知道变量是什么类型,直到它在运行时实际实例化。这也意味着可能为时已晚。TypeScript 向 JavaScript 添加了类型支持,并在编译到 JavaScript 期间捕获类型错误。如果你把牌打对,由某些变量是某种类型的错误假设引起的错误可以完全根除(你输入代码的严格程度或你输入代码完全取决于你)。

TypeScript 通过使用类型推断,使键入变得更容易,并且不那么明确。例如:在 TypeScript 中与 .该类型只是从其使用中推断出来的。即使您没有显式键入类型,它们仍然在那里,以防止您执行某些操作,否则会导致运行时错误。var x = "hello"var x : string = "hello"

默认情况下,TypeScript 是可选类型的。例如,TypeScript中的一个有效函数可以使用任何类型的参数调用它,即使用字符串调用它显然会导致运行时错误。就像你在JavaScript中习惯的那样。这是有效的,因为当没有显式分配类型并且无法推断类型时,就像在divideByTwo示例中一样,TypeScript将隐式分配类型。这意味着 divideByTwo 函数的类型签名会自动变为 。有一个编译器标志可以禁止此行为:.启用此标志可以提高安全性,但也意味着您必须执行更多键入操作。function divideByTwo(x) { return x / 2 }anyfunction divideByTwo(x : any) : any--noImplicitAny

类型具有与其关联的成本。首先,有一个学习曲线,其次,当然,使用适当的严格类型设置代码库也会花费你更多的时间。根据我的经验,这些成本在你与他人共享的任何严肃的代码库中都是完全值得的。Github中对编程语言和代码质量的大规模研究表明,“一般来说,静态类型语言比动态类型更不容易出现缺陷,并且在同一方面,强类型比弱类型更好”。

有趣的是,这篇论文发现TypeScript比JavaScript更不容易出错:

对于那些具有正系数的人,我们可以预期该语言与更多的缺陷修复相关联。这些语言包括C,C++,JavaScript,Objective-C,Php和Python。Clojure、Haskell、Ruby、Scala和TypeScript等语言都有负系数,这意味着这些语言导致缺陷修复提交的可能性低于平均水平。

增强的 IDE 支持

TypeScript的开发体验是对JavaScript的一大改进。TypeScript 编译器会实时通知 IDE 其丰富的类型信息。这提供了几个主要优点。例如,使用TypeScript,您可以安全地在整个代码库中进行重构,例如重命名。通过代码完成,您可以获得有关库可能提供的任何功能的内联帮助。不再需要记住它们或在在线参考资料中查找它们。编译错误在 IDE 中直接报告,并在您忙于编码时使用红色波浪线报告。总而言之,与使用JavaScript相比,这可以显着提高生产力。人们可以花更多的时间编码,更少的时间进行调试。

有各种各样的IDE对TypeScript有很好的支持,比如Visual Studio Code,WebStorm,Atom和Sublime。

严格的空检查

表单的运行时错误或通常由 JavaScript 代码中的错误引起。开箱即用的TypeScript已经降低了发生这些类型的错误的可能性,因为不能使用TypeScript编译器不知道的变量(类型化变量的属性除外)。但是,仍有可能错误地使用设置为 的变量。但是,使用2.0版本的TypeScript,您可以通过使用不可为 null 的类型来消除这些类型的错误。其工作原理如下:cannot read property 'x' of undefinedundefined is not a functionanyundefined

启用严格的空检查(编译器标志)后,TypeScript 编译器将不允许分配给变量,除非您显式声明它是可空的类型。例如,将导致编译错误。这完全符合类型论,因为它不是一个数字。可以定义为 的和类型并更正此错误:。--strictNullChecksundefinedlet x : number = undefinedundefinedxnumberundefinedlet x : number | undefined = undefined

一旦已知某个类型可以为空,这意味着它的类型也可以是值或,TypeScript 编译器就可以通过基于控制流的类型分析来确定您的代码是否可以安全地使用变量。换句话说,当您检查变量是否通过例如语句时,TypeScript编译器将推断出代码控制流的该分支中的类型不再为空,因此可以安全地使用。下面是一个简单的示例:nullundefinedundefinedif

let x: number | undefined;
if (x !== undefined) x += 1; // this line will compile, because x is checked.
x += 1; // this line will fail compilation, because x might be undefined.

在构建期间,TypeScript 的 2016 年会议联合设计师 Anders Hejlsberg 对此功能进行了详细的解释和演示:视频(从 44:30 到 56:30)。

汇编

要使用TypeScript,您需要一个构建过程来编译为JavaScript代码。构建过程通常只需要几秒钟,当然这取决于项目的大小。TypeScript 编译器支持增量编译(编译器标志),以便可以以更快的速度编译所有后续更改。--watch

TypeScript 编译器可以在生成的.js文件中内联源映射信息,也可以创建单独的 .map 文件。源代码映射信息可以通过调试实用程序(如Chrome DevTools和其他IDE)来使用,以将JavaScript中的行与TypeScript中生成的行相关联。这使您可以设置断点并在运行时直接在TypeScript代码上检查变量。源映射信息工作得很好,它在TypeScript之前很久就已经存在了,但是调试TypeScript通常不如直接使用JavaScript时那么好。以关键字为例。由于自ES2015以来围绕闭包的关键字的语义发生了变化,因此实际上可能在运行时作为调用的变量存在(请参阅此答案)。这可能会在调试期间使您感到困惑,但是如果您了解它或检查JavaScript代码,通常不是问题。应该指出的是,巴别塔也遭受了完全相同的问题。thisthisthis_this

TypeScript编译器还可以做一些其他技巧,例如基于装饰器生成拦截代码,为不同的模块系统生成模块加载代码以及解析JSX。但是,除了Typescript编译器之外,您还可能需要一个构建工具。例如,如果要压缩代码,则必须向生成过程添加其他工具才能执行此操作。

有TypeScript编译插件可用于WebpackGulpGrunt以及几乎任何其他JavaScript构建工具。TypeScript 文档中有一节是关于与涵盖所有这些构建工具的集成。还提供 linter,以防您想要更多的构建时检查。还有很多种子项目可以让你开始使用TypeScript,并结合一系列其他技术,如Angular 2,React,Ember,SystemJS,Webpack,Gulp等。

JavaScript 互操作性

Since TypeScript is so closely related to JavaScript it has great interoperability capabilities, but some extra work is required to work with JavaScript libraries in TypeScript. TypeScript definitions are needed so that the TypeScript compiler understands that function calls like or or are not in fact illegal statements. The definitions for these functions are placed in files._.groupByangular.copy$.fadeOut.d.ts

The simplest form a definition can take is to allow an identifier to be used in any way. For example, when using Lodash, a single line definition file will allow you to call any function you want on , but then, of course, you are also still able to make mistakes: would be a legal TypeScript call, but is, of course, an illegal call at run-time. If you want proper type support and code completion your definition file needs to to be more exact (see lodash definitions for an example).declare var _ : any__.foobar()

Npm modules that come pre-packaged with their own type definitions are automatically understood by the TypeScript compiler (see documentation). For pretty much any other semi-popular JavaScript library that does not include its own definitions somebody out there has already made type definitions available through another npm module. These modules are prefixed with "@types/" and come from a Github repository called DefinitelyTyped.

There is one caveat: the type definitions must match the version of the library you are using at run-time. If they do not, TypeScript might disallow you from calling a function or dereferencing a variable that exists or allow you to call a function or dereference a variable that does not exist, simply because the types do not match the run-time at compile-time. So make sure you load the right version of the type definitions for the right version of the library you are using.

To be honest, there is a slight hassle to this and it may be one of the reasons you do not choose TypeScript, but instead go for something like Babel that does not suffer from having to get type definitions at all. On the other hand, if you know what you are doing you can easily overcome any kind of issues caused by incorrect or missing definition files.

Converting from JavaScript to TypeScript

Any file can be renamed to a file and ran through the TypeScript compiler to get syntactically the same JavaScript code as an output (if it was syntactically correct in the first place). Even when the TypeScript compiler gets compilation errors it will still produce a file. It can even accept files as input with the flag. This allows you to start with TypeScript right away. Unfortunately, compilation errors are likely to occur in the beginning. One does need to remember that these are not show-stopping errors like you may be used to with other compilers..js.ts.js.js--allowJs

The compilation errors one gets in the beginning when converting a JavaScript project to a TypeScript project are unavoidable by TypeScript's nature. TypeScript checks all code for validity and thus it needs to know about all functions and variables that are used. Thus type definitions need to be in place for all of them otherwise compilation errors are bound to occur. As mentioned in the chapter above, for pretty much any JavaScript framework there are files that can easily be acquired with the installation of DefinitelyTyped packages. It might, however, be that you've used some obscure library for which no TypeScript definitions are available or that you've polyfilled some JavaScript primitives. In that case, you must supply type definitions for these bits for the compilation errors to disappear. Just create a file and include it in the tsconfig.json's array, so that it is always considered by the TypeScript compiler. In it declare those bits that TypeScript does not know about as type . Once you've eliminated all errors you can gradually introduce typing to those parts according to your needs..d.ts.d.tsfilesany

Some work on (re)configuring your build pipeline will also be needed to get TypeScript into the build pipeline. As mentioned in the chapter on compilation there are plenty of good resources out there and I encourage you to look for seed projects that use the combination of tools you want to be working with.

The biggest hurdle is the learning curve. I encourage you to play around with a small project at first. Look how it works, how it builds, which files it uses, how it is configured, how it functions in your IDE, how it is structured, which tools it uses, etc. Converting a large JavaScript codebase to TypeScript is doable when you know what you are doing. Read this blog for example on converting 600k lines to typescript in 72 hours). Just make sure you have a good grasp of the language before you make the jump.

Adoption

TypeScript is open-source (Apache 2 licensed, see GitHub) and backed by Microsoft. Anders Hejlsberg, the lead architect of C# is spearheading the project. It's a very active project; the TypeScript team has been releasing a lot of new features in the last few years and a lot of great ones are still planned to come (see the roadmap).

Some facts about adoption and popularity:

  • In the 2017 StackOverflow developer survey TypeScript was the most popular JavaScript transpiler (9th place overall) and won third place in the most loved programming language category.
  • In the 2018 state of js survey TypeScript was declared as one of the two big winners in the JavaScript flavors category (with ES6 being the other).
  • In the 2019 StackOverlow developer survey TypeScript rose to the 9th place of most popular languages amongst professional developers, overtaking both C and C++. It again took third place amongst most the most loved languages.
  • In the 2020 StackOverflow developer survey TypeScript was the second most loved technology.