如何解决typescript中使用generator无法使用for-of遍历(编译目标es5,使用node直接运行)的问题?

发布于 2022-09-06 21:04:43 字数 3071 浏览 27 评论 0

最近刚开始尝试typescript,想自己写个库练练手,当使用到生成器的时候发生了问题:

首先说明一下环境:

  1. Windows 10 64bit
  2. node.js 9.8.0
  3. typescript 2.7.2
  4. ts-node 5.0.1

若tsc编译目标为es5

编译时报告

test.ts(3,14): error TS2495: Type '{}' is not an array type or a string type.

但仍然生成了编译后的文件。在node中运行该文件的输出表明for-of遍历该生成器失败。

若tsc编译目标为es6

在nodejs中根本无法运行,因为用到了import

测试代码

// Generators.ts
import Random from './Random'

export default class Generators {
  static *range(a: number, b?: number) {
    if(b == undefined) {
      [a, b] = [0, a]
    }
    for(let i = a; i < b; i++) {
      yield i
    }
  }
}
// test.ts
import G from './Generators'

for(let i of G.range(10)) {
  console.log(i)
}

看起来仿佛没什么问题。

然而这是编译后的运行结果(node test.js):

<啥都没有>

没错,啥都没有23333

同样的代码,把import去掉直接在node里声明函数range并用for-of遍历是没问题的,代码如下:

function *range(a, b) {
  if(b == undefined) {
    [a, b] = [0, a]
  }
  for(let i = a; i < b; i++) {
    yield i
  }
}

for(let i of range(10)) {
  console.log(i)
}

输出如下,非常之正常(expected):

0
1
2
3
4
5
6
7
8
9
undefined

于是查看test.js,发现它是这个样子的:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Generators_1 = require("./Generators");
for (var _i = 0, _a = Generators_1.default.range(10); _i < _a.length; _i++) {
    var i = _a[_i];
    console.log(i);
}

猜测_a.length === undefined,导致循环直接退出,于是手动修改test.js以验证猜想,改成:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Generators_1 = require("./Generators");
console.log(Generators_1.default.range(10).length)
for (var _i = 0, _a = Generators_1.default.range(10); _i < _a.length; _i++) {
    var i = _a[_i];
    console.log(i);
}

再次运行(node test.js),输出结果:

undefined

果然这是一个expected unexpected error。

最后

所以可以说是typescript的问题了吗?还是有什么特别的技巧能解决这个问题?

真·最后

我又在ts-node的交互界面里执行了这段在node.js里正常执行的代码:

function *range(a, b) {
  if(b == undefined) {
    [a, b] = [0, a]
  }
  for(let i = a; i < b; i++) {
    yield i
  }
}

for(let i of range(10)) {
  console.log(i)
}

发现输出结果也是空的,直到我使用以下命令行参数启动ts-node

ts-node -O "{\"target\": \"esnext\"}"

然后再次输入那段代码,这才得到了正确的结果。

真·真·最后

我手贱又试了一下在node.js中以require的方式导入以es5为编译目标编译的Generators.js模块并再次试验:

let G = require('./Generators.js')

for(let i of G.default.range(10)) console.log(i)

输出:

0
1
2
3
4
5
6
7
8
9
undefined

输出十分的正常,毕竟G.default.range(10)实现了Symbol.iterator方法。

以上,不知道有没有大佬知道我哪里做错了或者解决的方法,感谢!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文