如何在Typescript中正确键入HOC?

时间:2019-03-25 13:52:57

标签: javascript reactjs typescript

如果我尝试使用从HOC传递过来的道具,则会收到有关道具类型缺失的错误。

我已经尝试了多种方法,但是经过一番研究,我想出了以下代码,从逻辑上讲,这对我来说似乎是正确的,但不幸的是,它不起作用。

这是我的解决方案:

interface INavigationContext {
  componentId?: string;
}

interface IAddNavigationContextProps {
  navigation: INavigationContext;
}

export function addNavigationContext<P extends object >(
  Component: React.ComponentType<P>,
): React.ComponentType<P & IAddNavigationContextProps> {
  const WrappedComponent: React.ComponentType<P & IAddNavigationContextProps> = (props: P) => (
    <NavigationContext.Consumer>
      {(navigationState: INavigationContext) => (
        <Component {...props as P} navigation={navigationState} />
      )}
    </NavigationContext.Consumer>
  );

  WrappedComponent.displayName = `addNavigationContext(${getDisplayName(WrappedComponent)})`;

  return WrappedComponent;
}

这是我得到的错误:

Property 'navigation' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'.

我希望如果包装这样的组件: addNavigationContext(MyComponent)

如果我在this.props.navigation内使用MyComponent,则不会出现类型错误

1 个答案:

答案 0 :(得分:0)

首先,您的HOC需要接收一个期望自己的PropsIAddNavigationContextProps

的组件。
Component: React.ComponentType<P & IAddNavigationContextProps>

第二,您的HOC需要返回一个仅期望其自己的Props

的组件。
React.ComponentType<P>

放在一起

export function addNavigationContext<P = {}>(
    Component: React.ComponentType<P & IAddNavigationContextProps>,
): React.ComponentType<P> {
    const WrappedComponent: React.FC<P> = props => (
        <NavigationContext.Consumer>
            {(navigationState: INavigationContext) => <Component {...props} navigation={navigationState} />}
        </NavigationContext.Consumer>
    );

    WrappedComponent.displayName = `addNavigationContext(${getDisplayName(WrappedComponent)})`;

    return WrappedComponent;
}

const MyComponent = addNavigationContext(({ children, navigation }) => <p>Magic</p>);