在下面的示例中,Flow似乎假设label
的类型为mixed
,即使Props声明和匿名函数声明都将其绑定到Node
。我错过了什么?
/* @flow */
import React from 'react';
import type { Node } from 'react';
type Props = {
values: { [string]: Node },
/* … */
};
export default class SelectButtons extends React.Component<Props> {
/* … */
createButtons(): Array<Node> {
return Object.entries(this.props.values).map(
([value: string, label: Node], index: number): Node => (
<button>
{label}
</button>
),
);
}
}
这是错误消息:
v------
44: <button
45: onClick={() => this.choose(value)}
46: key={index}
47: className={this.block('option', { selected: value === this.state.value })()}
48: >
^ React element `button`
v------
44: <button
45: onClick={() => this.choose(value)}
46: key={index}
47: className={this.block('option', { selected: value === this.state.value })()}
48: >
^ React element `button`. This type is incompatible with
v
170: props: {
171: children?: React$Node,
172: [key: string]: any,
173: },
^ object type. See lib: /tmp/flow/flowlib_3bead812/react-dom.js:170
Property `children` is incompatible:
49: {label}
^^^^^ mixed. This type is incompatible with
171: children?: React$Node,
^^^^^^^^^^ union: undefined | null | boolean | number | string | type application of type `React$Element` | type application of identifier `Iterable`. See lib: /tmp/flow/flowlib_3bead812/react-dom.js:171
Member 1:
15: | void
^^^^ undefined. See lib: /tmp/flow/flowlib_3bead812/react.js:15
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
15: | void
^^^^ undefined. See lib: /tmp/flow/flowlib_3bead812/react.js:15
Member 2:
16: | null
^^^^ null. See lib: /tmp/flow/flowlib_3bead812/react.js:16
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
16: | null
^^^^ null. See lib: /tmp/flow/flowlib_3bead812/react.js:16
Member 3:
17: | boolean
^^^^^^^ boolean. See lib: /tmp/flow/flowlib_3bead812/react.js:17
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
17: | boolean
^^^^^^^ boolean. See lib: /tmp/flow/flowlib_3bead812/react.js:17
Member 4:
18: | number
^^^^^^ number. See lib: /tmp/flow/flowlib_3bead812/react.js:18
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
18: | number
^^^^^^ number. See lib: /tmp/flow/flowlib_3bead812/react.js:18
Member 5:
19: | string
^^^^^^ string. See lib: /tmp/flow/flowlib_3bead812/react.js:19
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
19: | string
^^^^^^ string. See lib: /tmp/flow/flowlib_3bead812/react.js:19
Member 6:
20: | React$Element<any>
^^^^^^^^^^^^^^^^^^ type application of type `React$Element`. See lib: /tmp/flow/flowlib_3bead812/react.js:20
Error:
49: {label}
^^^^^ mixed. Inexact type is incompatible with exact type
20: | React$Element<any>
^^^^^^^^^^^^^^^^^^ exact type: object type. See lib: /tmp/flow/flowlib_3bead812/react.js:20
Member 7:
21: | Iterable<React$Node>;
^^^^^^^^^^^^^^^^^^^^ type application of identifier `Iterable`. See lib: /tmp/flow/flowlib_3bead812/react.js:21
Error:
49: {label}
^^^^^ mixed. This type is incompatible with
21: | Iterable<React$Node>;
^^^^^^^^^^^^^^^^^^^^ $Iterable. See lib: /tmp/flow/flowlib_3bead812/react.js:21
Property `@@iterator` is incompatible:
21: | Iterable<React$Node>;
^^^^^^^^^^^^^^^^^^^^ property `@@iterator` of $Iterable. Property not found in. See lib: /tmp/flow/flowlib_3bead812/react.js:21
49: {label}
^^^^^ mixed
答案 0 :(得分:1)
现在,我假设这是一个错误。如果您认为我错了,并且有更好的答案,请随时回答,我会很乐意接受!
我认为这是一个错误,因为以下解决方法:
createButtons(): Array<Node> {
return Object.keys(this.props.values).map((value: string, index: number): Node => (
<button>
{this.props.values[value]}
</button>
));
}
通过直接引用对象,而不是使用Object.entries
对其进行迭代,现在流程采用正确的类型。
Object.entries()
的回调参数属于Array<mixed> => void
类型。理想的类型是Array<[K, V]> => void
,其中K
和V
分别是对象的键和值类型(K
总是string
,I想。)
这将需要异构集合,其中Array<[K, V]>
由所有长度为2的数组居住,其第一个元素的类型为K
,第二个类型为V
。这可能需要Flow(目前)无法提供的某些类型级别的运算符和更高级的类型。
使用Object.keys
的解决方法有效,因为Object.keys
不需要异构数组(所有键都属于同一类型)但如果对象看起来不像{ [string]: X }
,它可能会失败但是,它具有不同类型的值(比如{ foo: number, bar: string }
,使它(再次)成为异构集合。