【问题标题】:Is it possible to compute type to react component props based on the presence or value of another prop using flow?是否可以使用流计算类型以根据另一个道具的存在或值对组件道具做出反应?
【发布时间】:2020-01-10 02:01:19
【问题描述】:

我正在尝试根据另一个值计算值的类型。如果 prop1 的类型是 x,那么 prop2 的类型应该是 y。

例如,在输入字段的情况下,

    <Input
     type="number"
     onChange={(value: number | string) => {}}
    />

如果 prop type="number" 那么来自 onChange 的 typeof 值应该是 numberstring 否则。我基本上是想在这里删除| 条件。

当我尝试这样调用输入时:

    <Input
     type="number"
     onChange={(value: number) => {}}
    />

Flow 抛出错误,因为如果使用 |,该值可以是数字或字符串。由于类型为"number",因此该值显然会编号。有没有办法让流程理解在这种情况下这将是数字?

Input 组件如下所示:

  type CommonProps = {
   disabled?: boolean,
   autoFocus?: boolean,
   placeholder: string
  };

  type PropsNumber = {
   type: 'number',
   onChange: (number) => void,
  };

  type PropsString = {
   type: 'string' | 'email',
   onChange: (string) => void,
  };

  type Props = CommonProps & (PropsNumber | PropsString);

  class Input extends React.Component<Props, {}> {
   render(){
     return (
        <input
          onChange={this.props.onChange}
          type={this.props.type}
          disabled={this.props.disabled}
          autoFocus={this.props.autoFocus}
        />
      );
    }
  }

在调用此组件的任何位置都会收到错误 Could not decide which case to select, since case 1 [1] may work but if it doesn't case 2 [2] looks promising too.。 为场景添加playground

【问题讨论】:

  • 虽然可能感觉不舒服,但我认为您所拥有的一切都很好,根据我的经验,通常是 Flow 中的“完成的事情”。

标签: reactjs flowtype


【解决方案1】:

解决这个问题的最佳方法是结合disjoint unions 和公共道具的类型传播:

import React from 'react';

type CommonProps = {|
    autoFocus?: boolean,
    placeholder?: string,
|};

type PropsNumber = {
  type: "number",
  onChange: number => void,
  ...CommonProps,
};

type PropsString = {
  type: "string",
  onChange: string => void,
  ...CommonProps,
};

type Props = PropsNumber | PropsString;

class Input extends React.Component<Props> {
  render() {
    if (this.props.type === "number") {
      this.props.onChange(5);
    } else {
      this.props.onChange("foo");
    }
    (this.props.autoFocus: ?boolean);
    // placeholder
    return null;
  }
}

<Input type="number" onChange={(value: number) => {}}/>;

<Input type="string" onChange={(value: string) => {}}/>;

// Expected error 
<Input type="number" onChange={(value: string) => {}}/>;

(playground)

这会通过 Flow,除了类型指定为 number 但回调接受 string 类型的参数的预期错误。

不建议将交集类型作为组合对象类型的一种方式。相反,应该使用类型展开,并且应该与exact types 一起使用。

请注意,当您优化 props 的类型以调用 onChange 时,如果您执行的操作比我这里的最小示例更复杂,您可能会遇到 refinement invalidations。您可以通过将值提取到 const 绑定中来解决这些问题。

【讨论】:

  • 感谢您的帮助。我尝试了您的答案,但在其他一些道具中出现错误。 (除了这两个之外,我还有其他组件的道具)。像type Props = (PropsNumber | PropsString) &amp; CommonProps; 一样尝试过。这有什么问题吗?这是错误流抛出Cannot create Input`元素,因为对象类型[1]中缺少属性onChange但存在于道具[2]中。Flow(InferError)`
  • 没有完整的例子很难说。编辑您的原始问题以使其更接近您的实际问题(并包含 flow.org/try 链接),或者如果您认为您的新问题有所不同,请创建一个新的顶级问题
  • 添加了一个更接近我的问题的 flow.org/try 链接。你能查一下吗?
  • 更新问题的其余部分以匹配 flow.org/try 链接,我再看看。事实上,这个问题令人困惑,如果我根据您的 flow.org/try 链接回答,我的回答也会让后来的人感到困惑。
  • 修改问题以匹配游乐场链接。
【解决方案2】:

type 脚本的创建正是为了确定值的类型,如果它是有条件的,它将失去意义......

在您的情况下,您最多可以选择两种不同的功能

onChange={
  type === "number" 
    ? (value: number) => {}
    : (value: string) => {}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 2021-09-30
    • 2020-10-09
    • 2018-11-01
    • 2018-05-03
    • 2019-07-23
    • 1970-01-01
    相关资源
    最近更新 更多