上下文使用者的HoC导致子组件类型错误

时间:2018-12-31 01:23:14

标签: reactjs typescript higher-order-components

我遇到一个问题,我试图编写HoC以便包装应该通过新注入的道具访问特定上下文的组件。

有一个与教程相关的Gist,基本上包含以下代码段:

export function withAppContext<
    P extends { appContext?: AppContextInterface },
    R = Omit<P, 'appContext'>
>(
    Component: React.ComponentClass<P> | React.StatelessComponent<P>
): React.SFC<R> {
    return function BoundComponent(props: R) {
        return (
            <AppContextConsumer>
                {value => <Component {...props} appContext={value} />}
            </AppContextConsumer>
        );
    };
}

类似地,another snippet here on SO如下所示:

function withTheme<P extends ThemeAwareProps>(Component: React.ComponentType<P>) {
    return function ThemedComponent(props: Pick<P, Exclude<keyof P, keyof ThemeAwareProps>>) {
        return (
            <ThemeContext.Consumer>
                {(theme) => <Component {...props} theme={theme} />}
            </ThemeContext.Consumer>
        )
    }
}

它们几乎相同,并且显然可以工作一次,但是情况不再如此。使用这两种变体,消耗的渲染道具中的子组件Component会带有以下错误消息加下划线:

Type '{ exploreContext: IExploreContextStore; }' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'.
    Property 'exploreContext' does not exist on type 'IntrinsicAttributes & P & { children?: ReactNode; }'.

发生问题的示例代码如下:

type WithExploreContext = { exploreContext?: IExploreContextStore };

export function withExploreContext<P extends WithExploreContext>(ChildComponent: ComponentType<P>) {
    return function WrappedComponent(
        props: Pick<P, Exclude<keyof P, keyof WithExploreContext>>
    ) {
        return <Consumer>{(value) => <ChildComponent {...props} exploreContext={value} />}</Consumer>;
    };
}

我几乎不知道这些摘要是什么问题,以及为什么它们不再按预期工作。

1 个答案:

答案 0 :(得分:1)

仅将props扩展到子组件是不够的。使用P将其投射到{...props as P}后,它便开始工作。

从3.2 behaviour of the spread operator for generics has changed开始。显然,props的类型会被消除,这是负面影响,但是您可以通过将其扩散回包装的组件时使用P将其投射回{...props as P}来解决此问题。