React + Typescript Ошибка функции высшего порядка "нельзя назначить типу" ошибка - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь написать функцию более высокого порядка для React в машинописном шрифте, которая: (1) требует определенных свойств обертываемого компонента (2) позволяет устанавливать свойства обернутых компонентов в обертке (3) имеет свойстваспецифично для оболочки

У меня в основном все работает, но когда я иду, чтобы установить свойства по умолчанию для анонимного класса, который оборачивает мой компонент, я получаю ошибку из машинописного текста, которую мне не удалось разрешить.

Я получаю ошибку:

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, но, похоже, ничего не работает.

Я использую машинописный код 3.3.1.

...