TypeScript不知道该组件是从HOC获取必需的道具

时间:2019-07-18 09:19:05

标签: javascript reactjs typescript high-order-component

我用HOC包装了我的组件的导出,这为它添加了支持,但是TypeScript看不到HOC已经添加了这个支持(必需)。

组件:

import * as React from "react";
import { withText } from "../hoc";

interface Props {
  text: string;
}

function TestComponent({ text }: Props) {
  return <div>{text}</div>;
}

export default withText(TestComponent);

HOC:

import * as React from "react";
import { useContext, ReactElement, ComponentType } from "react";
import { TextContext } from "../contexts";

const withText = <P extends object>(
  Component: ComponentType<P>
): ((props: P) => ReactElement) => props => (
  <Component text={useContext(TextContext).value} {...props} />
);

export default withText;

上下文:

import { createContext } from "react";

const TextContext = createContext<{ value: string }>({
  value: ""
});

export default TextContext;

应用程序:

import * as React from "react";
import { render } from "react-dom";
import { TextContext } from "./contexts";
import { TestComponent } from "./components";

function App() {
  return (
    <TextContext.Provider value={{ value: "Lorem ipsum" }}>
      <TestComponent /> /* TS throws an error here */
    </TextContext.Provider>
  );
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);

抛出TS的错误: Property 'text' is missing in type '{}' but required in type 'Props'

预期的行为:TypeScript知道withText HOC已经添加了“文本”属性

链接到codeandbox-> here

1 个答案:

答案 0 :(得分:1)

这应该对您有用

 type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
 interface InterfaceToOmit {
   text: string;
 }

    const withText = <P extends InterfaceToOmit>(Component: React.ComponentType<P>): React.ComponentClass<Omit<P, keyof InterfaceToOmit>> => {
      // tslint:disable-next-line:max-classes-per-file
      class MyHocClass extends React.Component<Omit<P, keyof InterfaceToOmit>> {
        public render() {
          return <Component text={'what ever your HOC component waht to pass here'} {...this.props as P} />;
        }
      }

      return MyHocClass;
    };

export default withText

您需要返回另一个将省略道具的组件。因此,当您使用withText时,它将成为仅具有这些道具的组件,而这些组件是您不想在HOC组件中传递的。在此示例中,其InterfaceToOmit

因此您的组件仍将具有所有道具

type propsToMyComponent = {
  anything: string;
} & InterfaceToOmit;

const testComponent = (props: propsToMyComponent) => {
  return <div>asd</div>;
};

然后像使用它

 const WithTextComponent = withText<propsToMyComponent>(testComponent);

现在你只能用一个道具叫它

<WithTextComponent anything={''} />; // no error