通用打字稿组件继承组件道具

时间:2018-12-22 16:27:51

标签: javascript reactjs typescript jsx tsx

我正在使用Typescript,我想对通用组件进行prop验证。我想创建一个Field组件,该组件呈现标签,错误消息和作为prop传递的组件。我进行了多次尝试,以使其正常运行,但是其中一部分或另一部分均无法通过。我也阅读了数十篇文章,但找不到任何人遇到完全相同的问题。

这是到目前为止我得到的:

interface IFieldProps<P> {
    is: React.ComponentType<P>;
}

class Field<P> extends React.PureComponent<IFieldProps<P>> {
    render() {
        const { is, ...rest } = this.props;

        const Component = is;

        return (
            <div>
                <Component {...rest} />
            </div>
        );
    }
}

interface ITextInputProps {
    value: string
}

class TextInput extends React.PureComponent<ITextInputProps> {
    render() {
        return (
            <input {...this.props} />
        );
    }
}

const render = () => <Field is={TextInput} />;

打字稿编译器并没有为value方法中缺少道具render而大喊大叫,因此我将使IFieldPropsP扩展,这应该使它起作用:

interface IFieldProps<P> extends P {
    is: React.ComponentType<P>;
}

编译器现在说“一个接口只能扩展一个类或另一个接口”。 好的,那么我将其设为一种类型,不用担心:

type IFieldProps<P> = P & {
    is: React.ComponentType<P>;
}

现在一切都搞砸了。在...rest上大喊“其他类型只能从对象类型创建”。在<Component />上大喊“ JSX元素类型'Component'没有任何构造或调用签名”。最后,在<Field />上大喊value道具缺失-同时,道具的自动完成功能在vscode中停止工作。 我认为,如果我对P施加一些约束(例如P extends {})可以解决一些问题,但事实并非如此。

如何制作通用组件,以继承作为道具传递的组件的道具?还是有些复杂?其他人如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

当包装的组件道具保留在另一个道具中(而不是与is混合使用)时,它起作用:

interface IFieldProps<P> {
  is: React.ComponentType<P>;
  props: P;
};

class Field<P> extends React.PureComponent<IFieldProps<P>> {
  render() {
      const { is, props } = this.props;

      const Component = is;

      return (
          <div>
              <Component {...props} />
          </div>
      );
  }
}

interface ITextInputProps {
  readonly value: string;
}

class TextInput extends React.PureComponent<ITextInputProps> {
  render() {
      return (
          <input {...this.props} />
      );
  }
}

const render = () => <Field is={TextInput} props={{ value: ''} } />;

我无法根据以下消息找到错误的来源:

  

输入“选择并   只读>,“子级” |排除>'不是   可分配给类型'IntrinsicAttributes&   LibraryManagedAttributes [“ is”],P和{子代?:   ReactNode; }>'。输入“ Pick&   只读>,“子级” |排除>'不是   可分配给类型'LibraryManagedAttributes [“ is”],P和   {子代?:ReactNode; }>'。