Pre*_*age 6 iterator generator typescript
在 TypeScript (3.6.3) Generator<>中几乎与IterableIterator<>相同。当Generator<>扩展Iterator<> 时,它默认第三个泛型参数(TNext)为unknown。Iterator<>本身默认TNext为undefined。所以Generator和Iterator(以及IterableIterator)并没有像他们应该的那样排列。
let gen2:IterableIterator<string>;
function* gen1():Generator<string> {
yield* gen2;
}
Run Code Online (Sandbox Code Playgroud)
yield* 行是一个错误:“无法将迭代委托给 value,因为其迭代器的 'next' 方法期望类型为 'undefined',但包含的生成器将始终发送 'unknown'.ts(2766)”。
我错过了什么吗?这有充分的理由吗?
dom*_*ndo 10
这实际上是一个非常复杂的问题。我不会假装完全理解它。但也许我可以提供一些见解。
(在此提交中)。Typescript 决定,无论好坏,它都希望对生成器进行更严格的类型检查。这实际上有一些正当的理由。看下面的例子
function* foo() {
let m = 0;
while (m < 10) {
yield m++;
}
return "done";
}
let gen = foo(),
curr;
while(!(curr = gen.next()).done) {}
// At his point we should know that
// curr.value is a string because curr.done is true
Run Code Online (Sandbox Code Playgroud)
在这里我们可以看到问题——我们不知道一个值是否被我们应该的所有逻辑规则返回或产生。所以他们推出了TReturn。TNext介绍:
[…]
yield根据生成器返回类型注释的下一个类型(即上面定义中的TNext类型)正确检查表达式的结果并为其提供类型Generator。
现在,如果您决定进行此类更改,您可能会破坏一些代码——目标是尽可能少地破坏。
我们必须注意,next()在生成器和非生成器迭代器中函数的使用存在惯用差异。正如ECMA-262对迭代器的评论。
参数可以传递给
next函数,但它们的解释和有效性取决于目标迭代器。for-of 语句和 Iterator 的其他常见用户不传递任何参数,因此期望以这种方式使用的 Iterator 对象必须准备好处理被无参数调用的情况。
迭代器主要用于不向 next 传递参数的 for-of 循环。实际上,将参数传递给下一个函数的情况非常罕见(MDN 甚至称其为“零参数函数”)。因此,默认值的唯一合理选项TNext是undefined。让它unknown成为类型检查的一大障碍(更不用说用 编译的代码了--strictNullChecks)。
如果next()使用生成器将参数传递给函数不是一种非常普遍的做法,那一切都会很棒——它实际上有一个有效的用例……并且在标准中定义了行为:
Generator.prototype.next(值)
该
next方法执行以下步骤:
- 令g为this值。
- 返回 ?GeneratorResume( g , value , empty)。
在MDN 中:
要发送到生成器的值。
该值将作为
yield表达式的结果进行分配。例如,在 中variable = yield expression,传递给.next()函数的值将被分配给variable。
更不用说,在典型的用例中,第一个.next()调用将在没有参数的情况下被调用,随后的调用将被调用。不幸的是,没有办法指定“可选的第一次,未知的后续时间”类型,所以我猜鉴于他们unknown为TNextin Generators解决了所有这些问题。
当然,没有完美的情况。但他们必须接受他们认为最不成问题的事情。
所有这些问题都在本期中为任何感兴趣的人进行了讨论。
| 归档时间: |
|
| 查看次数: |
921 次 |
| 最近记录: |