Skip to content

[@types/react] "Types of property 'render' are incompatible" using intersection type with 15.0.28 #17161

@mikebridge

Description

@mikebridge

Version 15.0.27 was able to correctly determine the type React.ComponentClass<P> that results from wrapping the Component in this function, but in version 15.0.28, the <Component ... /> line gives me the following error:

TS2605:JSX element type 'Component<P & IWithPersonalizationProps, ComponentState>' is not a constructor function for JSX elements.
  Types of property 'render' are incompatible.
    Type '() => false | Element' is not assignable to type '{ (): false | Element; (): Element; (): Element; (): Element; (): Element; (): Element; }'.
      Type 'false | Element' is not assignable to type 'Element'.
        Type 'false' is not assignable to type 'Element'.
import * as React from "react";

export interface IWithPersonalizationProps {
    name: string;
}

type HOC<PWrapped, PHoc> = React.ComponentClass<PWrapped & PHoc> | React.SFC<PWrapped & PHoc>;

export function withPersonalization<P, S>(Component: HOC<P, IWithPersonalizationProps>): React.ComponentClass<P> {

    class C extends React.Component<P & IWithPersonalizationProps, S> {

        public render(): JSX.Element {

            const {name, ...rest} = this.props as any;
            // ... todo: get the name from somewhere, e,g. the redux store.

            // the error occurs in the JSX component below:
            return ( 
                <Component name={name} {...rest} />
            );
        }
    }
    return C;
}

export default withPersonalization;

The purpose of this function is to wrap an arbitrary Component that implements IWithPersonalizationProps, and delegate the handling of the name prop to the withPersonalization wrapper. All the other props declared by Component are passed through, and the resulting component is typed with React.ComponentClass<P>. P therefore would be the type of the props of Component, minus the props described by IWithPersonalizationProps. The wrapped component might look like this:

interface ITestPersonalizedComponentOwnProps {
   greeting: string;
}

type TestPersonalizedComponentProps = 
        ITestPersonalizedComponentOwnProps 
        IWithPersonalizationProps &

class TestPersonalizedComponent extends React.Component<TestPersonalizedComponentProps, {}> {
    public render(): JSX.Element {
        return (<div>{this.props.greeting},, {this.props.name}</div>);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions