Typescript: Why doesn't Material-UI “withStyles()” work with an explicit constructor?
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
add a comment |
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
add a comment |
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
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
reactjs typescript material-ui
edited Nov 28 '18 at 23:46
Shorn
asked Oct 1 '18 at 6:36
ShornShorn
7,07833983
7,07833983
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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