我有一个自动完成功能,可以根据是否将prop multiple
传递给它来保存一个值或多个值。如果它是多个,那么它所保存的值将至少是一个空数组-永远不会为null。如果是单值自动完成,则该值确实可以为null。我正在努力正确地键入此类型,以便传递给它的onBlur
函数根据multiple
道具是否已传递给自动完成功能而知道期望使用哪种值类型。
Here's a link to the live flow.org testing page。我得到的错误出现在以下代码示例末尾的两行onBlur={...}
中。错误是:
39: | { multiple: true, onBlur: ValueT[] => void }
^ array type [1] is incompatible with null or undefined [2].
References:
39: | { multiple: true, onBlur: ValueT[] => void }
^ [1]
38: | { multiple: false, onBlur: ?ValueT => void }
^ [2]
39: | { multiple: true, onBlur: ValueT[] => void }
^ array type [1] is incompatible with `ValueT` [2].
References:
39: | { multiple: true, onBlur: ValueT[] => void }
^ [1]
38: | { multiple: false, onBlur: ?ValueT => void }
^ [2]
41: const AutocompleteWrapper = ({ multiple, onBlur }: AutocompleteWrapperT) => (
^ boolean literal `true` [1] is incompatible with boolean literal `false` [2].
References:
39: | { multiple: true, onBlur: ValueT[] => void }
^ [1]
38: | { multiple: false, onBlur: ?ValueT => void }
^ [2]
43: ? <AutocompleteMulti onBlur={onBlur} />
^ Cannot create `AutocompleteMulti` element because `ValueT` [1] is incompatible with array type [2] in the first argument of property `onBlur`.
References:
38: | { multiple: false, onBlur: ?ValueT => void }
^ [1]
20: type AutocompleteMultiPropsT = { onBlur: ValueT[] => void }
^ [2]
type ValueT = { id: number }
type SyntheticInputEventT = { target: { value: ?ValueT } }
type AutocompleteSinglePropsT = { onBlur: ?ValueT => void }
class AutocompleteSingle extends React.Component<AutocompleteSinglePropsT> {
onBlur = (e: SyntheticInputEventT) => {
this.props.onBlur(e.target.value || null)
}
render(): React.Node {
return <input onBlur={this.onBlur} />
}
}
type AutocompleteMultiPropsT = { onBlur: ValueT[] => void }
type AutocompleteMultiStateT = { value: ValueT[] }
class AutocompleteMulti extends React.Component<AutocompleteMultiPropsT, AutocompleteMultiStateT> {
values: ValueT[]
onBlur = (e: SyntheticInputEventT) => {
if (!e.target.value) return
this.values = [...this.values, e.target.value]
this.props.onBlur(this.values)
}
render(): React.Node {
return <input onBlur={this.onBlur} />
}
}
type AutocompleteWrapperT =
| { multiple: false, onBlur: ?ValueT => void }
| { multiple: true, onBlur: ValueT[] => void }
const AutocompleteWrapper = ({ multiple, onBlur }: AutocompleteWrapperT) => (
multiple
? <AutocompleteMulti onBlur={onBlur} />
: <AutocompleteSingle onBlur={onBlur} />
)
const CmpWithSingle = () => (
<AutocompleteWrapper onBlur={v => console.log(v ? v.id : null)} multiple={false} />
)
const CmpWithMulti = () => (
<AutocompleteWrapper onBlur={v => console.log(v.length)} multiple />
)
我也尝试过使用type="single"/"multiple"
而不是布尔multiple
道具,但这没有影响。我还尝试了以下替代方法来定义AutocompleteWrapperT
联合类型,但这会产生一些额外的流错误:
type BaseAutocompleteWrapperT<V, M: boolean> = {
multiple?: M,
onBlur: V => void
};
type AutocompleteWrapperT =
| BaseAutocompleteWrapperT<?ValueT, false>
| BaseAutocompleteWrapperT<ValueT[], true>
答案 0 :(得分:0)
Flow有一个unfortunate destructuring bug,在其中它不维护多个解构结果之间的关系。您可以通过避免在此处进行破坏来解决此问题:
const AutocompleteWrapper = (props: AutocompleteWrapperT) => (
props.multiple
? <AutocompleteMulti onBlur={props.onBlur} />
: <AutocompleteSingle onBlur={props.onBlur} />