如何使用流量键入es6生成器

时间:2018-12-11 21:09:06

标签: javascript react-native ecmascript-6 generator flowtype

我的react-native应用程序中有以下(简化的)代码(我认为react-native是无关紧要的,但这是我在其中发现错误的上下文)。

我正在尝试定义mystringgen的类型以使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,

1 个答案:

答案 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的标准类型定义,您可以在此处查看:

https://github.com/facebook/flow/blob/master/lib/core.js