TypeScript 不知道组件从 HOC 获取了 required prop
TypeScript doesn't know that component gets required prop from HOC
我正在用 HOC 包装我的组件的导出,这会向它添加 prop,但 TypeScript 看不到 HOC 已经添加了这个 prop(这是必需的)。
组件:
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 知道 'text' 属性已经由 withText HOC
添加
Link 到 codesandbox -> here
这应该适合你
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
您需要 return 另一个组件将省略道具。因此,当您使用 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
我正在用 HOC 包装我的组件的导出,这会向它添加 prop,但 TypeScript 看不到 HOC 已经添加了这个 prop(这是必需的)。
组件:
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 知道 'text' 属性已经由 withText HOC
添加Link 到 codesandbox -> here
这应该适合你
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
您需要 return 另一个组件将省略道具。因此,当您使用 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