Kyl*_*yle 6 javascript flowtype
我正在尝试创建Set的子类,因为我不能简单地从它扩展,我正在包装它的功能.
我正在尝试实现Symbol.iterator方法,但Flow没有.
这是我的代码:
/* @flow */
class CSet<T> {
_set: Set<T>;
[Symbol.iterator](): Iterator<T> {
return this._set[Symbol.iterator];
}
}
var a: CSet = new CSet();
for(var b of a){
}
core.js:309:5,29: property @@iterator
Property not found in
test.js:2:7,10: CSet
test.js:4:2,6:2:
computed property keys not supported
Run Code Online (Sandbox Code Playgroud)
第二个错误不是很大的交易,因为我可以很容易地压制它.我想知道我是不是一起做错了.
小智 5
因为Flow目前没有对符号的一般支持,它所表示的方式Symbol.iterator是hacky并且基本上阻止了在用户空间中定义迭代器的能力(它的支持仅适用于库定义):(
特别是Flow期望一个iterable上有一个@@iterator属性(当然不是一个有效的属性名称 - 但这是获得库定义支持的临时黑客).
因此,在获得正确的符号支持之前,最好的解决方法是为此模块创建一个库定义,使用此@@iterator属性进行Flow的理解:
// RealModule.js
export class CSet {
[Symbol.iterator]() {
return this._set[Symbol.iterator];
}
}
Run Code Online (Sandbox Code Playgroud)
.
// RealModule.FlowLibDef.js
declare module RealModule {
declare class CSet<T> {
_set: Set<T>;
@@iterator(): Iterator<T>;
}
}
Run Code Online (Sandbox Code Playgroud)
// @flow
class MyCollection<T> {
/*:: @@iterator(): Iterator<T> { return ({}: any); } */
// $FlowFixMe: computed property
[Symbol.iterator](): Iterator<T> {
// NOTE: this could just as easily return a different implementation
return new MyIterator(this);
}
}
class MyIterator<+T> {
/*:: @@iterator(): Iterator<T> { return (this: any); } */
// $FlowFixMe: computed property
[Symbol.iterator](): Iterator<T> {
return this;
}
next(): IteratorResult<T, void> {
return { done: false, value: someT };
// or return { done: true, value: undefined };
}
}
for (const value of new MyCollection()) {
console.log(value);
}
Run Code Online (Sandbox Code Playgroud)
这样做的原因是流将/*:: code */其解释为源中的流代码,只是它在运行时被注释掉,因此实际上不会影响代码。
Flow 本质上知道该@@iterator方法,尽管它不是有效的 JavaScript,因此我们将其定义为存在,返回Iterator<T>,并返回一个适用于它的值(即一个空对象转换为any)。
然后计算属性方法被流完全忽略,就好像它根本没有定义一样。Iterator<T>从方法中实际返回一个有效值是至关重要的,否则事情会在运行时中断。