当目标为ES5 / ES3时,TypeScript会转译什么内容?

19
我试图理解Typescript编译器何时会转换代码以使其与我指定的ECMAScript版本(ES5或ES3)兼容。
例如,TSC可以很好地转换for(var int of intArray),但它不会转换Number.isInteger()(根据w3schools,这是一个ES6特性)。 Number.isInteger()在IE<11.0中不受支持,所以这是一个问题。Visual Studio(和VS Code)没有提供不兼容警告,并且它不被转换。
我可以期望什么会被转换和什么不会被转换?我最初期望所有内容都将被转换,以便我不必跟踪这类事情,但似乎并非如此。

我认为TS处理这个问题的方式很像Promise<T>类型。也就是说,它假设你已经输入了一个polyfill。虽然Number.isInteger可以轻松地进行polyfill,但是polyfills并不是TS想要做的事情。例如,请参见关于polyfills的此评论 - Heretic Monkey
1
如果是这种情况,如果IDE能够提醒我代码与目标ECMAScript版本不兼容,那就太好了。我开始使用Number.isInteger()是因为Visual Studio向我提供了它,但后来才发现许多(相对较新的)浏览器不支持它。不确定还有什么其他的“地雷”等待着我! - JoshMB
最好使用类似es6-shim这样的东西,它可以填充许多可能缺失的功能,至少在您知道所针对的浏览器支持所有功能之前。 - Heretic Monkey
2个回答

21

TypeScript进行代码转译但不进行填充。因此,我们可以这样认为,任何在你的target中无效的语法都将被转换为有效的语法。例如,在目标设置为ES5时使用class关键字,它会将以下内容进行转译:

class Greeter {
}

变成这样:

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

(您可以在此处尝试更多操作。)

另一方面,它不会添加缺失的功能,您需要自己填充Number.isInteger()是有效的ES5语法,但这不是ES5中存在的功能。您可以通过导入babel-polyfill(它在底层使用core-js)或使用polyfill.io之类的服务自己进行填充。

注意:不要将lib选项与填充混淆。这个不会填充功能。它只是告诉TypeScript假装那些ES版本的功能已经存在,因此它会适当地进行类型检查。对于您支持的浏览器,您仍然需要自己处理填充部分。如果没有指定适当的lib,TypeScript将抱怨它不知道Number.isInteger()代表什么。

我不知道TypeScript转码了哪些功能的全面列表,但您可以在此处查看TypeScript+core-js填充的表格。 关于填充与转译的更多阅读资料,请参见这里


16

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

如上面的链接所述:

如果未指定--lib,则会注入默认库。注入的默认库为:
► 对于--target ES5:DOM、ES5、ScriptHost
► 对于--target ES6:DOM、ES6、DOM.Iterable、ScriptHost

所有不同的库都是项目的一部分

如果你的目标是es3或者es5,那么你不能使用Number.isInteger(),因为它是一个es6特性(正如你所说)。但是如果你有一个polyfill,你仍然可以使用es6库来定位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被转换为var,而for/in被转换为常规的forNumber.isInteger()是不同的功能,它在某些目标中不存在,例如Promise和'Symbol`。
编译器不会添加polyfill,需要您自己添加并告诉编译器它已经存在。

2
感谢您的回复。我正在寻找一种了解哪些功能类别将被转译,哪些不会被转译的方法。我相信对于那些在TypeScript项目上工作的人来说这是有意义的,但目前对我来说似乎有点随机。因此,这变成了一个猜测和检查的游戏。为什么for(var int of intArray)Number.isInteger()根本不同呢? - JoshMB
1
哦,这个有一个很好的解释。请查看我的修订答案。 - Nitzan Tomer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接