TypeScript中的Symbol.iterator

8

我想创建一个自定义可迭代对象。

这是我的代码的简化示例:

class SortedArray {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
        return 4;
    }
}
const testingIterables = new SortedArray();
for(let item of testingIterables as any) { // i have to cast it as any or it won't compile
    console.log(item);
}

这段代码在ES6上可以正常运行,但在TypeScript上编译后不会打印可迭代值。

这是TypeScript的一个bug还是我漏掉了什么?

谢谢。


除了Madara的回答之外,还有一个选项可以使用--downlevelIteration标志 - Kamil Solecki
1个回答

12

这不是一个错误。它取决于您的目标。

TypeScript做出了(在我看来很糟糕的)设计决策,如果您将TS for..of 转译为ES5或ES3,则会发出一个普通的for (var i; i < testingIterables.length; i++) 循环。

因此,对于ES5和ES3目标,仅允许在for..of循环中使用数组和字符串。

有几种解决方法:

  • 如果您的TypeScript版本高于2.3,则可以将downlevelIteration标志设置为true,这将使TypeScript正确编译迭代器,但这意味着您必须在运行时为不支持的浏览器提供Symbol.iterator polyfill,否则可能会在这些浏览器的意外位置引发运行时错误。
  • 选择一个更高的目标,如ES2015或更高版本。然后,您可以使用Babel进一步转译(您还需要运行时polyfill以使Symbols工作)。
  • 使用while和调用testingIterables.next()自己解开迭代器。

1
非常感谢。 看起来你是正确的,现在一切都正常了。 但我认为这仍然是一个错误。 我们必须将代码编译成ES5,对于一个声称是JavaScript超集的语言,如果它强制我们使用babel或自己解包ES6上运行良好的代码,那么这就不是程序员所期望的行为。 你不同意吗? - Yariv Katz
似乎TypeScript自TS2.3版本以来就有一个编译器标志:downlevelIteration,当设置为true时,它将假定您有一个Symbol.iterator的polyfill并按预期工作。我会在我的答案中添加这个。 - Madara's Ghost
谢谢,这让我非常清楚为什么更改目标突然导致出现“TS2489:迭代器必须具有'next()'方法”错误,这与正确实现迭代器接口的类有关。 - spiralx

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