【问题标题】:What will Typescript transpile when targeting ES5 / ES3?以 ES5 / ES3 为目标时,Typescript 会转译什么?
【发布时间】:2017-07-22 16:37:51
【问题描述】:

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

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

Number.isInteger() 在 IE

什么可以被编译,什么不能?我最初预计所有内容都会被转译,这样我就不必跟踪这样的事情,但事实似乎并非如此。

【问题讨论】:

  • 我相信 TS 处理这个很像 Promise<T> 类型。也就是说,它假设你已经输入了它,你已经有了一个 polyfill。虽然 Number.isInteger 是微不足道的 polyfill,但 polyfill 并不是 TS 想要做的事情。例如,请参阅this comment about polyfills
  • 如果是这种情况,如果 IDE 提醒我我的代码与我的目标 ECMAScript 版本不兼容,那就太好了。我开始使用 Number.isInteger() 是因为 Visual Studio 向我提供了它,但后来才发现许多(相对现代的)浏览器不支持它。不知道还有什么“地雷”在等着你!
  • 使用像es6-shim 这样的东西可能是个好主意,它可以填充很多可能丢失的东西,至少在你知道你的目标浏览器支持所有功能之前。

标签: typescript target transpiler


【解决方案1】:

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

class Greeter {
}

到这里:

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

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

另一方面,它不会添加缺少的功能,您必须自己polyfillNumber.isInteger() 是有效的 ES5 语法,只是 ES5 中不存在功能。您可以通过导入babel-polyfill(在后台使用core-js)或使用polyfill.io 之类的服务自行填充。

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

我不知道 TypeScript 转换的功能的完整列表,但您可以查看 TypeScript+core-js polyfills here 的表格。 更多关于 polyfill 与 transpilation 的阅读内容here

【讨论】:

    【解决方案2】:

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

    正如上面链接中所写:

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

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

    如果您的目标是es3es5,那么您不能使用Number.isInteger(),因为它(如您所说)是es6 功能。
    如果你有一个 polyfil,那么你仍然可以使用 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 变成了vars,for/in 变成了普通的for

    Number.isInteger() 有所不同,它是某些目标中不存在的功能,例如Promise 和“符号”。
    编译器不会添加 polyfill,由你来添加它,然后告诉编译器它就在那里。

    【讨论】:

    • 感谢您的回复。我正在寻找的是一种了解哪些功能类别将被转译和不会被转译的方法。我确信这对那些从事 Typescript 项目的人来说是有意义的,但目前它对我来说似乎有点随机。结果,它变成了一个猜测和检查的游戏。为什么for(var int of intArray)Number.isInteger() 根本不同?
    • 哦。有一个很好的解释。检查我修改后的答案。
    猜你喜欢
    • 1970-01-01
    • 2017-10-19
    • 2017-04-26
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    • 2018-05-29
    • 2021-11-06
    • 2014-12-12
    相关资源
    最近更新 更多