Skip to content
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

[TypeScript] Currently not possible to use business variables in a theme with "withStyles" #9192

Closed
simonvizzini opened this issue Nov 17, 2017 · 5 comments

Comments

@simonvizzini
Copy link
Contributor

simonvizzini commented Nov 17, 2017

I'm using TypeScript and I'm trying to define custom business variables in my theme, as described in the docs here.

This is what I have so far:

interface MyThemeExtension {
    status: {
        danger: string
    };
}

export const theme = createMuiTheme<MyThemeExtension>({
    status: {
        danger: orange[500]
    }
});

export type MyTheme = Theme<MyThemeExtension>;

But now I'm having trouble to use the withStyles HoC, because the theme argument of StyleRulesCallback is of type Theme. I'm no TS expert, but I think the types of Theme and StyleRulesCallback need to be changed to something like this (at least this worked for me):

-type StyleRulesCallback<ClassKey extends string = string> = (theme: Theme) => StyleRules<ClassKey>;
+type StyleRulesCallback<ClassKey extends string = string, T = {}> = (theme: Theme<T>) => StyleRules<ClassKey>;
-function withStyles<ClassKey extends string>(
+function withStyles<ClassKey extends string, T = {}>(
-  style: StyleRules<ClassKey> | StyleRulesCallback<ClassKey>,
+  style: StyleRules<ClassKey> | StyleRulesCallback<ClassKey, T>,
  options?: WithStylesOptions
): <P>(
  component: React.ComponentType<P & WithStyles<ClassKey>>
) => React.ComponentType<P & StyledComponentProps<ClassKey>>;

These changes allowed me to do: withStyles((theme: MyTheme) => ({...})

Again, I'm not sure if this is the correct way. Please let me know.

Your Environment

Tech Version
Material-UI 1.0.0-beta.21
React 16.1.1
TypeScript 2.5.3
@pelotom pelotom added the good first issue Great for first contributions. Enable to learn the contribution process. label Nov 19, 2017
@pelotom
Copy link
Member

pelotom commented Nov 22, 2017

There's a small problem with the proposed solution, which is that it isn't type safe. Since the place where the global theme is defined is divorced from the place where we want to use it, there's no way to enforce that your global theme is a MyTheme. In fact you could claim to have any old type of theme, anywhere you use withStyles, and the type system will just happily agree with you:

  withStyles((theme: Theme<{ foo: { bar: number } }>) => ({
    root: {
      lineHeight: theme.foo.bar,
    },
  }));

It may be an ok compromise to make, I just want to point out that it's really no safer than doing a cast like this:

  withStyles(theme => ({
    root: {
      backgroundColor: (theme as MyTheme).status.danger,
    },
  }));

In general this is making me wonder why there is any advantage to using withStyles with a callback, vs. exporting your theme from a module and then importing it everywhere that you want to use it:

// src/theme.ts

import createMuiTheme from 'material-ui/styles/createMuiTheme';
import { red, purple } from 'material-ui/colors';

export default createMuiTheme({
  palette: {
    primary: red,
    secondary: purple,
  },
  myCustomScalar: 3,
});
// src/component.ts

import * as React from 'react'
import { withStyles } from 'material-ui/styles'
import theme from './theme'

export default withStyles({
  root: {
    margin: theme.spacing.unit * theme.myCustomScalar
  }
})(...);

@mui mui deleted a comment from marcusjwhelan Nov 22, 2017
@mui mui deleted a comment from marcusjwhelan Nov 22, 2017
@mui mui deleted a comment from marcusjwhelan Nov 22, 2017
@pelotom pelotom removed the good first issue Great for first contributions. Enable to learn the contribution process. label Nov 22, 2017
@pelotom
Copy link
Member

pelotom commented Nov 22, 2017

Deleted some comments that were not pertinent to the issue.

@simonvizzini
Copy link
Contributor Author

Thanks for the insight, @pelotom! I totally agree that the proposed solution with regards to type safety doesn't make much sense, and so I will just import and use the theme directly, instead of using a callback with withStyles. Same for custom business variables, I'll just import them wherever I need them.

So this issue can be closed from my side.

@pelotom pelotom closed this as completed Nov 29, 2017
@gariggio
Copy link

gariggio commented Mar 20, 2018

Even though these bussines variables are theme related?

@pelotom
Copy link
Member

pelotom commented Mar 20, 2018

@gariggio I suggest taking a look at this page for the latest best practice for customizing the theme in TypeScript:

https://material-ui.com/guides/typescript/#customization-of-theme

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants