-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error using withStyles as decorator in TypeScript #8059
Comments
Here is the workaround I'm currently using: interface ExampleClasses {
root: string
}
interface ExampleProps {
text: string
classes: any
}
@withStyles<ExampleProps, ExampleClasses>({
root: {
color: 'blue'
}
})
export default class Example extends Component<ExampleProps, {}> {
render (): JSX.Element | null | false {
const classes = this.props.classes as ExampleClasses
const { text } = this.props
return <p className={classes.root}>{text}</p>
}
} |
@sbking I would keep the classes separate. Reason being is if you are using the component as a child then With this setup you get the autocompletion of you Styles with interface IStyles {
// styles interface
}
interface IHeaderInfoStyles {
classes: any;
}
interface IHeaderInfoProps {
// properties resulting from dispatches
}
interface IHeaderInfoInjectedProps {
// props injected from parent if any
}
interface IHeaderInfoDispatchProps {
// dispatches
}
interface IHeaderInfoState {
// your state for the class
}
type HeaderInfoProps = IHeaderInfoProps & IHeaderInfoInjectedProps & IHeaderInfoDispatchProps & IHeaderInfoStyles;
class HeaderInfo extends Component<HeaderInfoProps, IHeaderInfoState> {
export const HeaderInfo_container = withStyles<IHeaderInfoInjectedProps, IStyles>(styles)(
connect<IHeaderInfoProps, IHeaderInfoDispatchProps, (IHeaderInfoInjectedProps & IHeaderInfoStyles)>(mapStateToProps, mapDispatchToProps)(HeaderInfo),
); |
@marcusjwhelan Does that work with decorators, though? The example in my OP (with separate Props and Classes interfaces) works fine if you change it from using I'm slightly confused about your example, though. How would you access a JSS class from within the component? |
@sbking I am not exactly sure. I don't even know what JSS is. It should work with the decorator just fine. I don't use them. class HeaderInfo extends Component<HeaderInfoProps, IHeaderInfoState> {
constructor(props: HeaderInfoProps) {
super(props);
this.state = { /* your state init */};
}
} I am confused by the last part of your question but you should be able to access all the properties of dispatch, styles, props, because all the interfaces were |
@marcusjwhelan JSS is the system Material UI 1.0 uses internally for scoped CSS classes. Having a required https://github.com/callemall/material-ui/blob/v1-beta/src/Badge/Badge.js#L72 The Anyway, this will still not work as a decorator, because TypeScript enforces that class decorators return a type that is compatible with the original decorated class. The https://github.com/callemall/material-ui/blob/v1-beta/src/styles/withStyles.d.ts#L27 https://github.com/callemall/material-ui/blob/v1-beta/src/index.d.ts#L12-L16 If the inner component does not require a
|
@sbking in my code. You would simply use I see what you mean. The decorator will not work. Why must you use a decorator? But also this should be fixed. However. What is wrong with putting interface IExampleClasses {
root: string;
}
interface IExampleProps {
text: string;
}
interface IExampleStyles {
classes: any;
}
type PROPS = IExampleProps & IExampleStyles;
@withStyles<PROPS, IExampleClasses>({
root: {
color: 'blue',
},
})
class Example extends Component<PROPS, any> {
public render(): JSX.Element | null | false {
return <p className={this.props.classes.root}>{this.props.text}</p>;
}
} |
same issue here
|
I think my issue is the same or closely related:
Produces:
I created a stackoverflow question and someone gave a good explanation of the underlying cause and a workaround which I'm using for now. |
With the proposed changed from SO the usage as HOC would no longer work 😕 With Decorator@withStyles(styles)
class DecoratedComponent extends React.Component<
StyledComponentProps & { classes: StyledComponentClassNames }
> {
render() {
const { classes, text } = this.props;
return (
<div className={classes.root}>
{text}
</div>
);
}
} As Higher-Order Functionconst Component: React.SFC<
StyledComponentProps & { classes: StyledComponentClassNames }
> = ({ classes, text }) =>
<div className={classes.root}>
{text}
</div>;
const StyledComponent = withStyles<
StyledComponentProps,
StyledComponentClassNames
>(styles)(Component); I am not 100% sure if the issues are the same, the issue people are running into is something like this
which seems a common problem with Decorators and originates from the React typings (?): DefinitelyTyped/DefinitelyTyped#17161 |
¯_(ツ)_/¯ So ... I made a PR, which just overloads Would love some feedback if this patch breaks anyones code. |
Problem description
The withStyles function requires the wrapped component type to have a required
classes
prop, but the returned decorated class has an optionalclasses
prop. This causes thesetState
method signatures to differ, so TypeScript throws a compile error.Steps to reproduce
Minimal code example:
Compiler error:
Versions
The text was updated successfully, but these errors were encountered: