我发现我对 target 和 lib 选项以及它们如何与源代码中支持的功能交互感到困惑。我觉得文档需要改进一点,所以在提出问题之前在这里询问。
我天真地假设 target 指定了输出代码需要运行的 JS 版本(添加了一个模块加载器)。因此,我们始终可以在源代码中使用 TS 支持的所有高级 JS 功能(如对象扩展),并且编译器会为我们指定的目标生成合适的代码。我假设它手头有 polyfill 等,并且代码只会在目标 VM 上运行。
但是,lib 选项的文档指定默认库取决于目标。但是,库会影响可用的源类型,从而影响我们可以使用的代码。因此,我们可以使用的源特征取决于目标。这不像我预期的那样。我应该说我对 lib 的理解是它们使用不同的 API 进行输入,尽管文档并没有真正说明它们是什么。
我可以看到这里有一些不依赖于类型的语言特性和其他依赖于类型的语言特性。但是,目前尚不清楚这是否是造成这种情况的部分原因。
有人可以澄清一下吗?
第二个问题是,为什么 ES6 和 ES2015 库通常被记录为相同的东西。
谢谢
(这开始是一个评论,但它太长了。)
这有点令人困惑,部分原因是它背后有一些历史。我没有资格权威地回答这个问题,但我从早期开发就一直在关注 TypeScript,这是我的理解:
--target 告诉编译器在编译时要包含哪个库版本(例如,如果您使用 Promise,ES5 会给出编译器错误,但 ES6 会知道所有关于 Promise)以及编译器发出的 JS 版本(例如 ES5 将向下编译类语法,但 ES6 将保留它)。
--lib 是后来添加的,让您可以更好地控制编译时使用的库版本,而无需更改发出的 JS 目标。例如,一个常见问题是您可能包含 ES6 库功能的 polyfill,例如 Promise,但您希望通过向下编译类语法来定位 ES5 浏览器。在 --lib 出现之前,你要么必须以 ES6 为目标以避免编译有关 Promise 的错误,然后使用 Babel 再次向下编译,或者你可以以 ES5 为目标并为 Promise 提供你自己的类型定义,这样编译器就不会给你一个错误。现在使用 --lib 你可以简单地说你的 --target ES5 和 --lib ES6,编译器不会抱怨 Promise,但仍然会向下编译到 ES5。
正如您显然发现的那样,这两个选项都不会导致 TS 发出任何库 polyfill(Promise 等);您有责任提供正确的运行时库。它只发出一些低级语言兼容性帮助程序,例如 __extends 和 __awaiter(不同之处在于该类或异步不仅仅是可以在运行时填充的 API,它是一种具有语法含义的语言特性)。 --lib 选项只是根据您知道在运行时将要拥有的内容来获得正确级别的编译检查的方式。
至于为什么同时存在 ES6 和 ES2015,那只是因为 ECMAScript 更改了名称,而 TS 保留了旧名称作为向后兼容的有效选项。 :)
您会发现这些 TS 问题中涵盖了很多内容:
#4168 - 通过编译器设置规范化我们的 lib 文件
#6974 - 建议:模块化库
TSConfig 参考链接:
目标
库
-target
做了这两件事,加上一些语言特性是向下编译的,而另一些则不是,但确实需要一个库才能在源代码中使用..es6.d.ts
文件和es2015.d.ts
文件,但如果您使用--target es6
,则使用es6.d.ts
,它等效于--lib es6,dom,dom.iterable,scripthost
(如 {2 })。如果您单独使用--lib es6
,您将不会获得 DOM,等等。--lib es6
和--lib es2015
给您同样的东西。--target es6
和--target es2015
也为您提供相同的功能。