以 ES5 / ES3 为目标时,Typescript 会转译什么?

What will Typescript transpile when targeting ES5 / ES3?

我试图了解 Typescript 编译器何时会转换代码以使其与我指定的目标 ECMAScript 版本(ES5 或 ES3)兼容。

例如,TSC 可以很好地转译 for(var int of intArray),但不会转译 Number.isInteger()(根据 w3schools,这是 ES6 的一个特性)。

IE < 11.0 不支持

Number.isInteger(),所以这是一个问题。 Visual Studio(和 VS Code)不提供不兼容警告,也不会被转译。

什么可以转译,什么不能转译?我最初期望一切都会被转译,这样我就不必跟踪这样的事情,但事实似乎并非如此。

编译器支持基于您告诉它使用的库的功能。
有两种方法可以控制编译器将使用哪个库,使用 targetlib compiler options.

上面写的link:

If --lib is not specified a default library is injected. The default library injected is:
► For --target ES5: DOM,ES5,ScriptHost
► For --target ES6: DOM,ES6,DOM.Iterable,ScriptHost

所有不同的库都是 part of the project

如果您的目标是 es3es5,那么您不能使用 Number.isInteger(),因为它(如您所述)是一个 es6 功能。
如果你有一个 polyfil,那么你仍然可以使用 es6 lib:

来定位 es5
--target es5 --lib DOM,ES6,ScriptHost

或者您可以只复制 lib.es6.d.ts 的定义:

interface NumberConstructor {
    isInteger(number: number): boolean;
}

你可以使用 letconstfor/of 之类的东西而不考虑目标的原因是编译器知道如何生成等效代码,即使该功能不是'所选目标不支持。

例如:

const arr = [1, 2, 3];
for (let num of arr) {}

编译为:

var arr = [1, 2, 3];
for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
    var num = arr_1[_i];
}

如果没有指定目标。
可以看到,constlet变成了varfor/in变成了常规的for

Number.isInteger() 有所不同,它是某些目标中不存在的功能,例如 Promise 和 'Symbol`。
编译器不会添加 polyfill,由您自行添加,然后告诉编译器它就在那里。

TypeScript transpiles 但不 polyfill。因此,一种思考方式是 target 中的任何无效语法都将 转译 为有效语法。例如,当使用 class 关键字并将目标设置为 ES5 时,它将转译为:

class Greeter {
}

对此:

var Greeter = /** @class */ (function () {
    function Greeter() {
    }
    return Greeter;
}());

(你可以用这个 here 玩得更多。)

另一方面,它不会添加缺少的功能,您必须自己 polyfillNumber.isInteger() 是有效的 ES5 语法,它只是 ES5 中不存在的功能。你可以通过导入 babel-polyfill (which uses core-js under the hood) or using a service like polyfill.io.

来自己填充这个

注意:不要将 lib 选项与 polyfill 混淆。此 polyfill 功能。它只是告诉 TypeScript 就好像这些 ES 版本的特性存在一样,所以它会适当地对它们进行类型检查。对于您支持的浏览器,您仍然需要自己处理 polyfill 部分。如果你没有指定合适的 libs,TypeScript 会抱怨它不知道 Number.isInteger() 代表什么。

我不知道 TypeScript 转换功能的完整列表,但您可以看到 table TypeScript+core-js polyfills here。 更多关于 polyfill 与转译的阅读 here.