我的react-native应用程序中有以下(简化的)代码(我认为react-native是无关紧要的,但这是我在其中发现错误的上下文)。
我正在尝试定义mystring
和gen
的类型以使flow
感到高兴,但是我发现的唯一解决方案是string|void
,如下所示。下面的代码本身不会对流返回任何错误,但是一旦在其他地方使用mystring
,我就会收到错误,因为期望使用string
而不是void
。我玩过各种各样的组合,但是没有运气。
我应该如何修改此代码以纠正错误?
// @flow
import * as React from 'react';
type State = {
mystring: string|void,
};
type genType = Generator<string, void, void>;
export default class Example extends React.Component<{}, State> {
constructor(props: {}) {
super(props);
this.gen = this.makeGenerator();
const { value } = this.gen.next();
this.state = {
mystring: value,
};
}
gen: genType;
* makeGenerator(): genType {
yield 'somestring';
}
render() {
const { mystring } = this.state;
return mystring.charAt(0);
}
}
在上面的代码上运行flow
时,在最后一行(这是强制流将mystring
视为字符串的示例)
Cannot call mystring.charAt because property charAt is missing in undefined [1].
[1] 5│ mystring?: string,
答案 0 :(得分:2)
对于Generator
的引用类型,参数看起来像这样:
interface Generator<+Yield,+Return,-Next>
当您致电next()
时,会得到以下结果:
type IteratorResult<+Yield,+Return> =
| { done: true, +value?: Return }
| { done: false, +value: Yield };
您可以在done: true
情况下看到Flow假设结果中的value
属性可能不存在。这意味着,无论您如何键入生成器,Flow都会假设value
的类型在这种情况下可能是void
。但是在done: false
情况下,Flow将使用您指定为生成器的Yield
类型的任何类型。因此,您可以像这样检查done
的值以优化value
的类型:
const result = this.gen.next();
if (!result.done) {
this.state = {
mystring: result.value,
};
}
对!result.done
的检查将result
的类型细化为{ done: false, +value: Yield }
,这为string
给出了value
的类型,而{{ 1}}值。
通过该更改,您可以更新状态类型,以从void
的类型联合中删除void
:
mystring
上面type State = {
mystring: string,
};
和Generator
的定义来自Flow的标准类型定义,您可以在此处查看: