Можно ли вычислить тип для реагирования компонентов реквизита на основе наличия или стоимости другого реквизита с использованием потока? - PullRequest
1 голос
/ 06 января 2020

Я пытаюсь вычислить тип значения на основе другого. Если тип prop1 равен x, тогда тип prop2 должен быть y.

Например, в случае поля ввода,

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

, если prop type="number", тогда typeof value из onChange должно быть number и string в противном случае. Я в основном пытаюсь удалить условие | здесь.

Когда я пытаюсь вызвать Input следующим образом:

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

Поток выдает ошибку, потому что значение может быть либо число или строка, если используется |. Значение в этом случае, очевидно, будет иметь номер, поскольку тип - "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. везде, где вызывается этот компонент. Добавление игровая площадка к сценарию.

Ответы [ 2 ]

2 голосов
/ 06 января 2020

Лучший способ решить эту проблему - использовать комбинацию непересекающихся союзов и типового спреда для общих реквизитов:

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) => {}}/>;

( детская площадка )

Это передает поток, за исключением ожидаемой ошибки, когда тип указан как number, но обратный вызов принимает аргумент типа string.

Типы пересечений не рекомендуются в качестве способа объединения типы объектов. Вместо этого следует использовать тип распространения, и он должен использоваться с точными типами .

Обратите внимание, что при уточнении типа props для вызова onChange, если вы делаете что-то более сложное, чем мой минимальный пример, здесь вы можете столкнуться с уточнениями . Вы сможете обойти их, вытягивая значения в const привязки.

0 голосов
/ 06 января 2020
Сценарий типа

был создан именно для того, чтобы определить тип значения. Если оно будет условным, оно потеряет смысл ...

В вашем случае самое большее, что вы можете сделать, - это условие с выбором двух разных функций.

onChange={
  type === "number" 
    ? (value: number) => {}
    : (value: string) => {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...