981377660LMT / ts

ts学习
6 stars 1 forks source link

tsc 编译结果不正确(迭代器) #529

Open 981377660LMT opened 1 month ago

981377660LMT commented 1 month ago

遍历Map:

for (var _b = 0, _c =mp.keys(); _b < _c.length; _b++) {
...
}

但是IterableIterator是没有length

tsc 配置需要开启downlevelIteration

 let result = ts.transpileModule(fileContent, { compilerOptions: { module: ts.ModuleKind.ES2022, downlevelIteration: true } })

变成了:

try {
  for (var _e = __values(mp.keys()), _f = _e.next(); !_f.done; _f = _e.next()) {}
} catch (e_3_1) {
  e_3 = { error: e_3_1 }
}

var __values =
  (this && this.__values) ||
  function (o) {
    var s = typeof Symbol === 'function' && Symbol.iterator,
      m = s && o[s],
      i = 0
    if (m) return m.call(o)
    if (o && typeof o.length === 'number')
      return {
        next: function () {
          if (o && i >= o.length) o = void 0
          return { value: o && o[i++], done: !o }
        }
      }
    throw new TypeError(s ? 'Object is not iterable.' : 'Symbol.iterator is not defined.')
  }
981377660LMT commented 1 month ago

downlevelIteration 是 TypeScript 编译器的一个选项,用于在生成 ES5 或 ES3 代码时,提供对迭代器和生成器的支持。默认情况下,TypeScript 会生成与目标 ECMAScript 版本兼容的代码,但在某些情况下,特别是当你需要支持 ES5 或 ES3 时,可能需要额外的帮助来处理迭代器和生成器。

为什么需要 downlevelIteration

在 ES2015 (ES6) 中引入了迭代器和生成器,这些特性在 ES5 或 ES3 中并不存在。如果你将 TypeScript 编译目标设置为 ES5 或 ES3,并且你的代码使用了这些 ES2015 特性,TypeScript 默认情况下会报错或生成不兼容的代码。

downlevelIteration 选项的作用就是让 TypeScript 编译器生成额外的代码,以在 ES5 或 ES3 环境中模拟这些 ES2015 特性。

示例

假设你有以下 TypeScript 代码:

for (const item of [1, 2, 3]) {
  console.log(item);
}

如果你将编译目标设置为 ES5,并且没有启用 downlevelIteration,TypeScript 会生成类似以下的代码:

for (var _i = 0, _a = [1, 2, 3]; _i < _a.length; _i++) {
  var item = _a[_i];
  console.log(item);
}

这虽然可以工作,但如果你启用了 downlevelIteration,TypeScript 会生成更复杂的代码来模拟 ES2015 的迭代器行为:

var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function() {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};

var e_1, _a;
try {
    for (var _b = __values([1, 2, 3]), _c = _b.next(); !_c.done; _c = _b.next()) {
        var item = _c.value;
        console.log(item);
    }
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
    try {
        if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
    }
    finally { if (e_1) throw e_1.error; }
}

这段代码使用了辅助函数 __values 来模拟 ES2015 的迭代器行为。

总结

downlevelIteration 选项使得 TypeScript 能够在编译到 ES5 或 ES3 时,提供对 ES2015 迭代器和生成器的支持,通过生成额外的代码来模拟这些特性。这在需要兼容旧版 JavaScript 运行环境时非常有用。

981377660LMT commented 1 month ago

要开启downlevelIteration,才能支持es6之后的迭代器语法

981377660LMT commented 1 month ago

downlevelIteration 是 TypeScript 编译器的一个选项,它提供了对 ES2015 或更高版本中引入的迭代器和生成器特性的改进支持,当目标是 ES5 或 ES3 时。这个选项主要影响 for..of 循环、扩展操作符(...)、解构赋值和 Array.from 方法的编译输出。 为什么需要 downlevelIteration? 在 ES2015(也称为 ES6)及以后的版本中,引入了新的迭代协议,包括迭代器(Iterator)和可迭代对象(Iterable)。这些新特性允许 JavaScript 对象自定义它们被 for..of 循环遍历的方式。 然而,当 TypeScript 的目标设置为 ES5 或 ES3 时,这些基于 ES2015 的迭代特性默认不会被完全支持,因为 ES5/ES3 环境本身并不支持这些新的迭代协议。默认情况下,TypeScript 会将 for..of 循环转换为基于索引的 for 循环,这种转换只适用于数组类型,但不适用于其他可迭代对象,如 Set 或 Map。 启用 downlevelIteration 选项后,TypeScript 会生成更复杂的代码,以在 ES5/ES3 环境中模拟 ES2015 的迭代行为,从而支持对非数组对象的迭代。