React + TypeScript高阶函数“不可分配给类型”错误

3
我将为您翻译如下内容,这是一篇关于IT技术的文章:

我正试图在typescript中编写一个React高阶函数,它具有以下功能: (1)要求被包装的组件拥有特定的属性 (2)允许在包装器上设置被包装组件的属性 (3)具有特定于包装器的属性

我基本上已经使所有东西都运作了,但当我尝试在包装我的组件的匿名类上设置默认属性时,typescript会报错,而我无法解决。

我得到的错误信息是:

src/withContainer.tsx:33:3 - error TS2322: Type 'typeof (Anonymous class)' is not assignable to type 'ComponentClass<P & ContainerProps, any>'.
  Types of property 'defaultProps' are incompatible.
    Type '{ loading: Element; }' is not assignable to type 'Partial<P & ContainerProps>'.

 33   return class extends React.Component<P & ContainerProps, ContainerState> {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 34     // Why does typescript say this is an error?
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 80     }
    ~~~~~
 81   };
    ~~~~

以下是我想要做的示例:

这里是一个我想要实现的示例:

import * as React from "react";

/**
 * Properties specific to the container component.
 */
export interface ContainerProps {
  /* eslint-disable @typescript-eslint/no-explicit-any */
  loading: React.ReactElement<any>;
}

export interface ContainerState {
  data: {};

  initialized: boolean;
}

/**
 * Components being wrapped need a putData function on them.
 */
export interface PuttableProps {
  /**
   * Put data into state on the parent component.
   *
   * @param data Data to be put into state.
   */
  putData(data: object): void;
}

/* eslint-disable max-lines-per-function */
export function withContainer<P>(
  WrappedComponent: React.ComponentType<P & PuttableProps>
): React.ComponentClass<P & ContainerProps> {
  return class extends React.Component<P & ContainerProps, ContainerState> {
    // Why does typescript say this is an error?
    static defaultProps = {
      loading: <React.Fragment />
    };

    state: ContainerState = {
      initialized: false,
      data: {}
    };

    /**
     * After mounting, simulate loading data and mark initialized.
     */
    componentDidMount(): void {
      // Simulate remote data load, 2 minutes after we mounted set initialized to true
      setTimeout(() => {
        this.setState({
          initialized: true
        });
      }, 2000);
    }

    /**
     * Set data as state on the parent component.
     */
    private putData = (data: object): void => {
      this.setState({ data });
    };

    /**
     * Render the wrapped component.
     */
    render(): React.ReactNode {
      // If we haven't initialized the document yet, don't return the component
      if (!this.state.initialized) {
        return this.props.loading;
      }

      // Whatever props were passed from the parent, our data and our putData function
      const props = {
        ...this.props,
        ...this.state.data,
        putData: this.putData
      };

      return <WrappedComponent {...props} />;
    }
  };
}

export class ClickCounter extends React.Component<
  PuttableProps & { count: number },
  {}
> {
  static defaultProps = {
    count: 0
  };

  increment = () => {
    this.props.putData({ count: this.props.count + 1 });
  };

  render(): React.ReactNode {
    return (
      <div>
        <h1>{this.props.count}</h1>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

而它可以这样利用:

import React from "react";
import ReactDOM from "react-dom";
import { withContainer, ClickCounter } from "./withContainer";

const WrappedClickCounter = withContainer(ClickCounter);
const component = (
  <WrappedClickCounter count={0} loading={<div>Loading...</div>} />
);

ReactDOM.render(component, document.getElementById("root"));


我尝试了几种变化,包括让P扩展ContainerProps,但似乎都不起作用。 我正在使用typescript 3.3.1版本。
2个回答

1
正如错误所述,您的defaultPropsContainerProps类型不匹配。具体而言,在ContainerProps中,您有{isLoading:ReactElement<any>},但是您的defaultProps类型为{loading:Element}
我建议您将ContainerProps定义为以下内容:
import type { ReactNode } from 'react';

export interface ContainerProps {
  isLoading: ReactNode
}

0
你解决了这个问题吗?在你返回组件的那一行,你尝试使用Partial了吗?
return class extends React.Component<P & ContainerProps...

你可以试试这个吗?

return class extends React.Component<Partial<P & ContainerProps>....

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接