TypeScript和React组件,均接受TextArea和Input的onChange

时间:2018-12-27 10:45:46

标签: reactjs typescript

我是TypeScript的新手,我正在尝试创建一个输入组件,如果它收到type="text",它将呈现input,如果它收到type="textarea",则呈现textarea。问题是当我在代码上与onChange一起使用组件时,打字稿正在抱怨,似乎不允许我在同一事件上使用两种类型?

它告诉我:

Type '(e: ChangeEvent<HTMLInputElement>) => void' is not assignable to type '(e?: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement> | undefined) => void'.
Types of parameters 'e' and 'e' are incompatible.
Type 'ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement> | undefined' is not assignable to type 'ChangeEvent<HTMLInputElement>'.
Type 'undefined' is not assignable to type 'ChangeEvent<HTMLInputElement>'.

input.js

interface InputProps {
  className?: string;
  type?: string;
  placeholder?: string;
  onChange?: (e?: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
}

const Input: FunctionComponent<InputProps> = ({ type = 'text', ...props }) => {
  if (type === 'textarea') {
    return <textarea {...props} />;
  }
  return <input type={type} {...props} />;
};

用法:

class Usage extends React.Component<State> {
  state: State;

  onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    this.setState({ input: e.target.value });
  };

  render() {
    return (
        <Input placeholder="Write an something..." onChange={this.onInputChange} />
    );
  }
}

我该如何解决?


更新

我暂时解决此问题的方法是说事件可以是any类型,但这有点可笑

type CommonProps = {
  className?: string;
  placeholder?: string;
  type?: string;
  onChange?: (e: any) => void;
};

2 个答案:

答案 0 :(得分:0)

如果要使用打字稿,则需要创建一个类。 正常功能不允许在打字稿道具类型中使用|

这应该是您的Input.js文件:

export interface IInputProps {
  className?: string;
  type?: string;
  placeholder?: string;
  onChange?: (e?: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
}

export class Input extends React.Component<IInputProps, {}> {
  constructor(props: IInputProps) {
    super(props);
  }
  render() {
    const { props, props: { type } } = this;
    if (type === 'textarea') {
      return <textarea {...props} />;
    }
    return <input type={type} {...props} />;
  }
}

这是如何使用它:

class Usage extends React.Component<State> {
  state: State;

  onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    this.setState({ input: e.target.value });
  };

  render() {
    return (
      <Input placeholder="Write an something..." onChange={this.onInputChange} />
    );
  }
}

这将是InputTextArea的评估方式:

enter image description here

答案 1 :(得分:0)

您可以使用有区别的联合来传递两种类型的参数,一种用于text,另一种用于textarea。这样可以确保处理程序和类型保持同步。

type InputProps = { // The common Part
    className?: string;
    placeholder?: string;
} & ({ // The discriminated union
    type?: "text";
    onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
} | {
    type: "textarea";
    onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
})

const Input: FunctionComponent<InputProps> = (props: InputProps) => {
    if (props.type === 'textarea') {
        return <textarea {...props} />;
    }
    return <input {...props} />;
};


class Usage extends React.Component<State> {
    state: State;

    onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        this.setState({ input: e.target.value });
    };

    render() {
        return (
            <Input placeholder="Write an something..." onChange={this.onInputChange} />
        );
    }
}