Typescript: Why doesn't Material-UI “withStyles()” work with an explicit constructor?












4















Edit:



Note that the incorrect constructor was generated by IntelliJ IDEA. This has now been fixed, see: https://youtrack.jetbrains.com/issue/WEB-35178





I am looking at using Material-UI in my app, but I'm having some trouble with the withStyles styling solution in combination with TypeScript.



I'm trying to make my own little wrapper component, based off the Popper documentation.



The problem is, if I define a constructor explicitly the way I'm used to ((B) in the code below), then this line:



export default withStyles(styles)(HelpComponent);


Give this error:



ERROR in [at-loader] ./src/main/ts/screen/keyword/HelpComponent.tsx:150:35 
TS2345: Argument of type 'typeof HelpComponent' is not assignable to parameter of type 'ComponentType<never>'.
Type 'typeof HelpComponent' is not assignable to type 'StatelessComponent<never>'.
Type 'typeof HelpComponent' provides no match for the signature '(props: never, context?: any): ReactElement<any> | null'.


The only way I've been able to make this work is to omit the explicit constructor and define state as a field ((A) in the code below).



Is there a way to declare a constructor the normal way when I use withStyles?



I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?



Ultimately, I just don't understand that TypeScript error message - can anyone explain what it's trying to say?



import {
createStyles,
Paper,
Popper,
Theme,
WithStyles,
withStyles
} from '@material-ui/core';
import * as React from 'react';
import {ReactNode, SyntheticEvent} from 'react';
import {EventUtil} from "appUtil/EventUtil";
import {WarningSvg} from "component/svg-icon/WarningSvg";
let log = require("log4javascript").getLogger("HelpComponent");

export interface HelpComponentProps extends WithStyles<typeof styles> {
children:ReactNode;
}

export interface HelpComponentState {
open:boolean;
arrowRef?: HTMLElement;
}

class HelpComponent extends React.Component<HelpComponentProps, HelpComponentState> {
helpRef!: HTMLElement;

// (A)
state = {open: false, arrowRef: undefined};

// (B)
// constructor(props: HelpComponentProps, context: HelpComponentState){
// super(props, context);
// this.state = {open: false, arrowRef: undefined};
// }

handleClick = (event:SyntheticEvent<any>) => {
EventUtil.stopClick(event);
this.setState({open: !this.state.open,});
};

handleArrowRef = (node:HTMLElement) => {
this.setState({
arrowRef: node,
});
};

render(){
const {classes} = this.props;
return <span ref={(ref)=>{if(ref) this.helpRef = ref}}>
<WarningSvg onClick={this.handleClick}/>
<Popper id={"help-popper"} className={classes.popper} transition
open={this.state.open} anchorEl={this.helpRef}
modifiers={{arrow:{enabled:true, element: this.state.arrowRef}}}
>
<span className={classes.arrow} ref={this.handleArrowRef}/>
<Paper className={classes.paper}>{this.props.children}</Paper>
</Popper>
</span>;
}

}

const styles = (theme: Theme) => createStyles({
root: {
flexGrow: 1,
},
scrollContainer: {
height: 400,
overflow: 'auto',
marginBottom: theme.spacing.unit * 3,
},
scroll: {
position: 'relative',
width: '230%',
backgroundColor: theme.palette.background.paper,
height: '230%',
},
legend: {
marginTop: theme.spacing.unit * 2,
maxWidth: 300,
},
paper: {
maxWidth: 400,
overflow: 'auto',
},
select: {
width: 200,
},
popper: {
zIndex: 1,
'&[x-placement*="bottom"] $arrow': {
top: 0,
left: 0,
marginTop: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '0 1em 1em 1em',
borderColor: `transparent transparent ${theme.palette.common.white} transparent`,
},
},
'&[x-placement*="top"] $arrow': {
bottom: 0,
left: 0,
marginBottom: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '1em 1em 0 1em',
borderColor: `${theme.palette.common.white} transparent transparent transparent`,
},
},
'&[x-placement*="right"] $arrow': {
left: 0,
marginLeft: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 1em 1em 0',
borderColor: `transparent ${theme.palette.common.white} transparent transparent`,
},
},
'&[x-placement*="left"] $arrow': {
right: 0,
marginRight: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 0 1em 1em',
borderColor: `transparent transparent transparent ${theme.palette.common.white}`,
},
},
},
arrow: {
position: 'absolute',
fontSize: 7,
width: '3em',
height: '3em',
'&::before': {
content: '""',
margin: 'auto',
display: 'block',
width: 0,
height: 0,
borderStyle: 'solid',
},
},
});

export default withStyles(styles)(HelpComponent);


Versions:




  • "typescript": "3.0.3"

  • "@types/react": "16.4.14"

  • "@types/react-dom": "16.0.7"

  • "@material-ui/core": "3.1.1"

  • "webpack": "4.19.1"










share|improve this question





























    4















    Edit:



    Note that the incorrect constructor was generated by IntelliJ IDEA. This has now been fixed, see: https://youtrack.jetbrains.com/issue/WEB-35178





    I am looking at using Material-UI in my app, but I'm having some trouble with the withStyles styling solution in combination with TypeScript.



    I'm trying to make my own little wrapper component, based off the Popper documentation.



    The problem is, if I define a constructor explicitly the way I'm used to ((B) in the code below), then this line:



    export default withStyles(styles)(HelpComponent);


    Give this error:



    ERROR in [at-loader] ./src/main/ts/screen/keyword/HelpComponent.tsx:150:35 
    TS2345: Argument of type 'typeof HelpComponent' is not assignable to parameter of type 'ComponentType<never>'.
    Type 'typeof HelpComponent' is not assignable to type 'StatelessComponent<never>'.
    Type 'typeof HelpComponent' provides no match for the signature '(props: never, context?: any): ReactElement<any> | null'.


    The only way I've been able to make this work is to omit the explicit constructor and define state as a field ((A) in the code below).



    Is there a way to declare a constructor the normal way when I use withStyles?



    I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?



    Ultimately, I just don't understand that TypeScript error message - can anyone explain what it's trying to say?



    import {
    createStyles,
    Paper,
    Popper,
    Theme,
    WithStyles,
    withStyles
    } from '@material-ui/core';
    import * as React from 'react';
    import {ReactNode, SyntheticEvent} from 'react';
    import {EventUtil} from "appUtil/EventUtil";
    import {WarningSvg} from "component/svg-icon/WarningSvg";
    let log = require("log4javascript").getLogger("HelpComponent");

    export interface HelpComponentProps extends WithStyles<typeof styles> {
    children:ReactNode;
    }

    export interface HelpComponentState {
    open:boolean;
    arrowRef?: HTMLElement;
    }

    class HelpComponent extends React.Component<HelpComponentProps, HelpComponentState> {
    helpRef!: HTMLElement;

    // (A)
    state = {open: false, arrowRef: undefined};

    // (B)
    // constructor(props: HelpComponentProps, context: HelpComponentState){
    // super(props, context);
    // this.state = {open: false, arrowRef: undefined};
    // }

    handleClick = (event:SyntheticEvent<any>) => {
    EventUtil.stopClick(event);
    this.setState({open: !this.state.open,});
    };

    handleArrowRef = (node:HTMLElement) => {
    this.setState({
    arrowRef: node,
    });
    };

    render(){
    const {classes} = this.props;
    return <span ref={(ref)=>{if(ref) this.helpRef = ref}}>
    <WarningSvg onClick={this.handleClick}/>
    <Popper id={"help-popper"} className={classes.popper} transition
    open={this.state.open} anchorEl={this.helpRef}
    modifiers={{arrow:{enabled:true, element: this.state.arrowRef}}}
    >
    <span className={classes.arrow} ref={this.handleArrowRef}/>
    <Paper className={classes.paper}>{this.props.children}</Paper>
    </Popper>
    </span>;
    }

    }

    const styles = (theme: Theme) => createStyles({
    root: {
    flexGrow: 1,
    },
    scrollContainer: {
    height: 400,
    overflow: 'auto',
    marginBottom: theme.spacing.unit * 3,
    },
    scroll: {
    position: 'relative',
    width: '230%',
    backgroundColor: theme.palette.background.paper,
    height: '230%',
    },
    legend: {
    marginTop: theme.spacing.unit * 2,
    maxWidth: 300,
    },
    paper: {
    maxWidth: 400,
    overflow: 'auto',
    },
    select: {
    width: 200,
    },
    popper: {
    zIndex: 1,
    '&[x-placement*="bottom"] $arrow': {
    top: 0,
    left: 0,
    marginTop: '-0.9em',
    width: '3em',
    height: '1em',
    '&::before': {
    borderWidth: '0 1em 1em 1em',
    borderColor: `transparent transparent ${theme.palette.common.white} transparent`,
    },
    },
    '&[x-placement*="top"] $arrow': {
    bottom: 0,
    left: 0,
    marginBottom: '-0.9em',
    width: '3em',
    height: '1em',
    '&::before': {
    borderWidth: '1em 1em 0 1em',
    borderColor: `${theme.palette.common.white} transparent transparent transparent`,
    },
    },
    '&[x-placement*="right"] $arrow': {
    left: 0,
    marginLeft: '-0.9em',
    height: '3em',
    width: '1em',
    '&::before': {
    borderWidth: '1em 1em 1em 0',
    borderColor: `transparent ${theme.palette.common.white} transparent transparent`,
    },
    },
    '&[x-placement*="left"] $arrow': {
    right: 0,
    marginRight: '-0.9em',
    height: '3em',
    width: '1em',
    '&::before': {
    borderWidth: '1em 0 1em 1em',
    borderColor: `transparent transparent transparent ${theme.palette.common.white}`,
    },
    },
    },
    arrow: {
    position: 'absolute',
    fontSize: 7,
    width: '3em',
    height: '3em',
    '&::before': {
    content: '""',
    margin: 'auto',
    display: 'block',
    width: 0,
    height: 0,
    borderStyle: 'solid',
    },
    },
    });

    export default withStyles(styles)(HelpComponent);


    Versions:




    • "typescript": "3.0.3"

    • "@types/react": "16.4.14"

    • "@types/react-dom": "16.0.7"

    • "@material-ui/core": "3.1.1"

    • "webpack": "4.19.1"










    share|improve this question



























      4












      4








      4


      0






      Edit:



      Note that the incorrect constructor was generated by IntelliJ IDEA. This has now been fixed, see: https://youtrack.jetbrains.com/issue/WEB-35178





      I am looking at using Material-UI in my app, but I'm having some trouble with the withStyles styling solution in combination with TypeScript.



      I'm trying to make my own little wrapper component, based off the Popper documentation.



      The problem is, if I define a constructor explicitly the way I'm used to ((B) in the code below), then this line:



      export default withStyles(styles)(HelpComponent);


      Give this error:



      ERROR in [at-loader] ./src/main/ts/screen/keyword/HelpComponent.tsx:150:35 
      TS2345: Argument of type 'typeof HelpComponent' is not assignable to parameter of type 'ComponentType<never>'.
      Type 'typeof HelpComponent' is not assignable to type 'StatelessComponent<never>'.
      Type 'typeof HelpComponent' provides no match for the signature '(props: never, context?: any): ReactElement<any> | null'.


      The only way I've been able to make this work is to omit the explicit constructor and define state as a field ((A) in the code below).



      Is there a way to declare a constructor the normal way when I use withStyles?



      I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?



      Ultimately, I just don't understand that TypeScript error message - can anyone explain what it's trying to say?



      import {
      createStyles,
      Paper,
      Popper,
      Theme,
      WithStyles,
      withStyles
      } from '@material-ui/core';
      import * as React from 'react';
      import {ReactNode, SyntheticEvent} from 'react';
      import {EventUtil} from "appUtil/EventUtil";
      import {WarningSvg} from "component/svg-icon/WarningSvg";
      let log = require("log4javascript").getLogger("HelpComponent");

      export interface HelpComponentProps extends WithStyles<typeof styles> {
      children:ReactNode;
      }

      export interface HelpComponentState {
      open:boolean;
      arrowRef?: HTMLElement;
      }

      class HelpComponent extends React.Component<HelpComponentProps, HelpComponentState> {
      helpRef!: HTMLElement;

      // (A)
      state = {open: false, arrowRef: undefined};

      // (B)
      // constructor(props: HelpComponentProps, context: HelpComponentState){
      // super(props, context);
      // this.state = {open: false, arrowRef: undefined};
      // }

      handleClick = (event:SyntheticEvent<any>) => {
      EventUtil.stopClick(event);
      this.setState({open: !this.state.open,});
      };

      handleArrowRef = (node:HTMLElement) => {
      this.setState({
      arrowRef: node,
      });
      };

      render(){
      const {classes} = this.props;
      return <span ref={(ref)=>{if(ref) this.helpRef = ref}}>
      <WarningSvg onClick={this.handleClick}/>
      <Popper id={"help-popper"} className={classes.popper} transition
      open={this.state.open} anchorEl={this.helpRef}
      modifiers={{arrow:{enabled:true, element: this.state.arrowRef}}}
      >
      <span className={classes.arrow} ref={this.handleArrowRef}/>
      <Paper className={classes.paper}>{this.props.children}</Paper>
      </Popper>
      </span>;
      }

      }

      const styles = (theme: Theme) => createStyles({
      root: {
      flexGrow: 1,
      },
      scrollContainer: {
      height: 400,
      overflow: 'auto',
      marginBottom: theme.spacing.unit * 3,
      },
      scroll: {
      position: 'relative',
      width: '230%',
      backgroundColor: theme.palette.background.paper,
      height: '230%',
      },
      legend: {
      marginTop: theme.spacing.unit * 2,
      maxWidth: 300,
      },
      paper: {
      maxWidth: 400,
      overflow: 'auto',
      },
      select: {
      width: 200,
      },
      popper: {
      zIndex: 1,
      '&[x-placement*="bottom"] $arrow': {
      top: 0,
      left: 0,
      marginTop: '-0.9em',
      width: '3em',
      height: '1em',
      '&::before': {
      borderWidth: '0 1em 1em 1em',
      borderColor: `transparent transparent ${theme.palette.common.white} transparent`,
      },
      },
      '&[x-placement*="top"] $arrow': {
      bottom: 0,
      left: 0,
      marginBottom: '-0.9em',
      width: '3em',
      height: '1em',
      '&::before': {
      borderWidth: '1em 1em 0 1em',
      borderColor: `${theme.palette.common.white} transparent transparent transparent`,
      },
      },
      '&[x-placement*="right"] $arrow': {
      left: 0,
      marginLeft: '-0.9em',
      height: '3em',
      width: '1em',
      '&::before': {
      borderWidth: '1em 1em 1em 0',
      borderColor: `transparent ${theme.palette.common.white} transparent transparent`,
      },
      },
      '&[x-placement*="left"] $arrow': {
      right: 0,
      marginRight: '-0.9em',
      height: '3em',
      width: '1em',
      '&::before': {
      borderWidth: '1em 0 1em 1em',
      borderColor: `transparent transparent transparent ${theme.palette.common.white}`,
      },
      },
      },
      arrow: {
      position: 'absolute',
      fontSize: 7,
      width: '3em',
      height: '3em',
      '&::before': {
      content: '""',
      margin: 'auto',
      display: 'block',
      width: 0,
      height: 0,
      borderStyle: 'solid',
      },
      },
      });

      export default withStyles(styles)(HelpComponent);


      Versions:




      • "typescript": "3.0.3"

      • "@types/react": "16.4.14"

      • "@types/react-dom": "16.0.7"

      • "@material-ui/core": "3.1.1"

      • "webpack": "4.19.1"










      share|improve this question
















      Edit:



      Note that the incorrect constructor was generated by IntelliJ IDEA. This has now been fixed, see: https://youtrack.jetbrains.com/issue/WEB-35178





      I am looking at using Material-UI in my app, but I'm having some trouble with the withStyles styling solution in combination with TypeScript.



      I'm trying to make my own little wrapper component, based off the Popper documentation.



      The problem is, if I define a constructor explicitly the way I'm used to ((B) in the code below), then this line:



      export default withStyles(styles)(HelpComponent);


      Give this error:



      ERROR in [at-loader] ./src/main/ts/screen/keyword/HelpComponent.tsx:150:35 
      TS2345: Argument of type 'typeof HelpComponent' is not assignable to parameter of type 'ComponentType<never>'.
      Type 'typeof HelpComponent' is not assignable to type 'StatelessComponent<never>'.
      Type 'typeof HelpComponent' provides no match for the signature '(props: never, context?: any): ReactElement<any> | null'.


      The only way I've been able to make this work is to omit the explicit constructor and define state as a field ((A) in the code below).



      Is there a way to declare a constructor the normal way when I use withStyles?



      I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?



      Ultimately, I just don't understand that TypeScript error message - can anyone explain what it's trying to say?



      import {
      createStyles,
      Paper,
      Popper,
      Theme,
      WithStyles,
      withStyles
      } from '@material-ui/core';
      import * as React from 'react';
      import {ReactNode, SyntheticEvent} from 'react';
      import {EventUtil} from "appUtil/EventUtil";
      import {WarningSvg} from "component/svg-icon/WarningSvg";
      let log = require("log4javascript").getLogger("HelpComponent");

      export interface HelpComponentProps extends WithStyles<typeof styles> {
      children:ReactNode;
      }

      export interface HelpComponentState {
      open:boolean;
      arrowRef?: HTMLElement;
      }

      class HelpComponent extends React.Component<HelpComponentProps, HelpComponentState> {
      helpRef!: HTMLElement;

      // (A)
      state = {open: false, arrowRef: undefined};

      // (B)
      // constructor(props: HelpComponentProps, context: HelpComponentState){
      // super(props, context);
      // this.state = {open: false, arrowRef: undefined};
      // }

      handleClick = (event:SyntheticEvent<any>) => {
      EventUtil.stopClick(event);
      this.setState({open: !this.state.open,});
      };

      handleArrowRef = (node:HTMLElement) => {
      this.setState({
      arrowRef: node,
      });
      };

      render(){
      const {classes} = this.props;
      return <span ref={(ref)=>{if(ref) this.helpRef = ref}}>
      <WarningSvg onClick={this.handleClick}/>
      <Popper id={"help-popper"} className={classes.popper} transition
      open={this.state.open} anchorEl={this.helpRef}
      modifiers={{arrow:{enabled:true, element: this.state.arrowRef}}}
      >
      <span className={classes.arrow} ref={this.handleArrowRef}/>
      <Paper className={classes.paper}>{this.props.children}</Paper>
      </Popper>
      </span>;
      }

      }

      const styles = (theme: Theme) => createStyles({
      root: {
      flexGrow: 1,
      },
      scrollContainer: {
      height: 400,
      overflow: 'auto',
      marginBottom: theme.spacing.unit * 3,
      },
      scroll: {
      position: 'relative',
      width: '230%',
      backgroundColor: theme.palette.background.paper,
      height: '230%',
      },
      legend: {
      marginTop: theme.spacing.unit * 2,
      maxWidth: 300,
      },
      paper: {
      maxWidth: 400,
      overflow: 'auto',
      },
      select: {
      width: 200,
      },
      popper: {
      zIndex: 1,
      '&[x-placement*="bottom"] $arrow': {
      top: 0,
      left: 0,
      marginTop: '-0.9em',
      width: '3em',
      height: '1em',
      '&::before': {
      borderWidth: '0 1em 1em 1em',
      borderColor: `transparent transparent ${theme.palette.common.white} transparent`,
      },
      },
      '&[x-placement*="top"] $arrow': {
      bottom: 0,
      left: 0,
      marginBottom: '-0.9em',
      width: '3em',
      height: '1em',
      '&::before': {
      borderWidth: '1em 1em 0 1em',
      borderColor: `${theme.palette.common.white} transparent transparent transparent`,
      },
      },
      '&[x-placement*="right"] $arrow': {
      left: 0,
      marginLeft: '-0.9em',
      height: '3em',
      width: '1em',
      '&::before': {
      borderWidth: '1em 1em 1em 0',
      borderColor: `transparent ${theme.palette.common.white} transparent transparent`,
      },
      },
      '&[x-placement*="left"] $arrow': {
      right: 0,
      marginRight: '-0.9em',
      height: '3em',
      width: '1em',
      '&::before': {
      borderWidth: '1em 0 1em 1em',
      borderColor: `transparent transparent transparent ${theme.palette.common.white}`,
      },
      },
      },
      arrow: {
      position: 'absolute',
      fontSize: 7,
      width: '3em',
      height: '3em',
      '&::before': {
      content: '""',
      margin: 'auto',
      display: 'block',
      width: 0,
      height: 0,
      borderStyle: 'solid',
      },
      },
      });

      export default withStyles(styles)(HelpComponent);


      Versions:




      • "typescript": "3.0.3"

      • "@types/react": "16.4.14"

      • "@types/react-dom": "16.0.7"

      • "@material-ui/core": "3.1.1"

      • "webpack": "4.19.1"







      reactjs typescript material-ui






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 28 '18 at 23:46







      Shorn

















      asked Oct 1 '18 at 6:36









      ShornShorn

      7,07833983




      7,07833983
























          1 Answer
          1






          active

          oldest

          votes


















          3














          If you look at the definition of React.ComponentType:



          type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;


          The alternative you are trying to use is ComponentClass, which is defined as:



          interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
          new (props: P, context?: any): Component<P, S>;
          // ...
          }


          Notice that the context parameter is optional (? mark). The problem is that the context parameter of your constructor is not optional, so HelpComponent is not compatible with callers that expect to be able to omit the context argument. If you make the parameter optional, the error should go away.



          When TypeScript reports the error that typeof HelpComponent is not assignable to the union type React.ComponentType, it semi-arbitrarily picks one member of the union type to report a detailed error. Unfortunately, it didn't pick the one you intended, so the error message isn't very useful.




          I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?




          Yes, by overriding the state property, you may be unintentionally changing its type to be something different from the state type argument that you passed to the React.Component base class.






          share|improve this answer
























          • Ohhhhh, snap. Thankyou for the quick answer.

            – Shorn
            Oct 2 '18 at 8:07











          • Thanks. I needed to make the context as optional.

            – Murat Karagöz
            Nov 19 '18 at 14:02












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52585706%2ftypescript-why-doesnt-material-ui-withstyles-work-with-an-explicit-constru%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          If you look at the definition of React.ComponentType:



          type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;


          The alternative you are trying to use is ComponentClass, which is defined as:



          interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
          new (props: P, context?: any): Component<P, S>;
          // ...
          }


          Notice that the context parameter is optional (? mark). The problem is that the context parameter of your constructor is not optional, so HelpComponent is not compatible with callers that expect to be able to omit the context argument. If you make the parameter optional, the error should go away.



          When TypeScript reports the error that typeof HelpComponent is not assignable to the union type React.ComponentType, it semi-arbitrarily picks one member of the union type to report a detailed error. Unfortunately, it didn't pick the one you intended, so the error message isn't very useful.




          I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?




          Yes, by overriding the state property, you may be unintentionally changing its type to be something different from the state type argument that you passed to the React.Component base class.






          share|improve this answer
























          • Ohhhhh, snap. Thankyou for the quick answer.

            – Shorn
            Oct 2 '18 at 8:07











          • Thanks. I needed to make the context as optional.

            – Murat Karagöz
            Nov 19 '18 at 14:02
















          3














          If you look at the definition of React.ComponentType:



          type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;


          The alternative you are trying to use is ComponentClass, which is defined as:



          interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
          new (props: P, context?: any): Component<P, S>;
          // ...
          }


          Notice that the context parameter is optional (? mark). The problem is that the context parameter of your constructor is not optional, so HelpComponent is not compatible with callers that expect to be able to omit the context argument. If you make the parameter optional, the error should go away.



          When TypeScript reports the error that typeof HelpComponent is not assignable to the union type React.ComponentType, it semi-arbitrarily picks one member of the union type to report a detailed error. Unfortunately, it didn't pick the one you intended, so the error message isn't very useful.




          I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?




          Yes, by overriding the state property, you may be unintentionally changing its type to be something different from the state type argument that you passed to the React.Component base class.






          share|improve this answer
























          • Ohhhhh, snap. Thankyou for the quick answer.

            – Shorn
            Oct 2 '18 at 8:07











          • Thanks. I needed to make the context as optional.

            – Murat Karagöz
            Nov 19 '18 at 14:02














          3












          3








          3







          If you look at the definition of React.ComponentType:



          type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;


          The alternative you are trying to use is ComponentClass, which is defined as:



          interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
          new (props: P, context?: any): Component<P, S>;
          // ...
          }


          Notice that the context parameter is optional (? mark). The problem is that the context parameter of your constructor is not optional, so HelpComponent is not compatible with callers that expect to be able to omit the context argument. If you make the parameter optional, the error should go away.



          When TypeScript reports the error that typeof HelpComponent is not assignable to the union type React.ComponentType, it semi-arbitrarily picks one member of the union type to report a detailed error. Unfortunately, it didn't pick the one you intended, so the error message isn't very useful.




          I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?




          Yes, by overriding the state property, you may be unintentionally changing its type to be something different from the state type argument that you passed to the React.Component base class.






          share|improve this answer













          If you look at the definition of React.ComponentType:



          type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;


          The alternative you are trying to use is ComponentClass, which is defined as:



          interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
          new (props: P, context?: any): Component<P, S>;
          // ...
          }


          Notice that the context parameter is optional (? mark). The problem is that the context parameter of your constructor is not optional, so HelpComponent is not compatible with callers that expect to be able to omit the context argument. If you make the parameter optional, the error should go away.



          When TypeScript reports the error that typeof HelpComponent is not assignable to the union type React.ComponentType, it semi-arbitrarily picks one member of the union type to report a detailed error. Unfortunately, it didn't pick the one you intended, so the error message isn't very useful.




          I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?




          Yes, by overriding the state property, you may be unintentionally changing its type to be something different from the state type argument that you passed to the React.Component base class.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 1 '18 at 12:43









          Matt McCutchenMatt McCutchen

          14.3k821




          14.3k821













          • Ohhhhh, snap. Thankyou for the quick answer.

            – Shorn
            Oct 2 '18 at 8:07











          • Thanks. I needed to make the context as optional.

            – Murat Karagöz
            Nov 19 '18 at 14:02



















          • Ohhhhh, snap. Thankyou for the quick answer.

            – Shorn
            Oct 2 '18 at 8:07











          • Thanks. I needed to make the context as optional.

            – Murat Karagöz
            Nov 19 '18 at 14:02

















          Ohhhhh, snap. Thankyou for the quick answer.

          – Shorn
          Oct 2 '18 at 8:07





          Ohhhhh, snap. Thankyou for the quick answer.

          – Shorn
          Oct 2 '18 at 8:07













          Thanks. I needed to make the context as optional.

          – Murat Karagöz
          Nov 19 '18 at 14:02





          Thanks. I needed to make the context as optional.

          – Murat Karagöz
          Nov 19 '18 at 14:02




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52585706%2ftypescript-why-doesnt-material-ui-withstyles-work-with-an-explicit-constru%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Lallio

          Futebolista

          Jornalista