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

Unparameterize Theme type #9295

Merged
merged 1 commit into from
Nov 27, 2017
Merged

Unparameterize Theme type #9295

merged 1 commit into from
Nov 27, 2017

Conversation

pelotom
Copy link
Member

@pelotom pelotom commented Nov 25, 2017

I don't think there's a reason for Theme to have a type parameter. There's not really any benefit to having it currently (see #9192), and to make it useful would require making things un-type safe. I don't see the point of attaching "business variables" to a theme; one should just export one's business variables from a module, and import them in one's component modules, and everything is type safe. But if you really want to attach arbitrary variables to a theme, it's impossible to make this type safe, so we shouldn't lie and pretend it is. One can just cast the theme, e.g.

withStyles(theme => ({
  root: {
    lineHeight: (theme as MyTheme).myBusinessVariable
  }
}))

@pelotom pelotom requested a review from sebald November 25, 2017 08:21
@mbrookes mbrookes added the flow label Nov 25, 2017
@mbrookes
Copy link
Member

@pelotom Does this change anything in the docs?

@pelotom pelotom added typescript and removed flow labels Nov 25, 2017
@pelotom
Copy link
Member Author

pelotom commented Nov 25, 2017

@mbrookes no, it shouldn’t. Also FYI this pertains to TypeScript only, not Flow.

@sebald sebald merged commit be0d4fd into mui:v1-beta Nov 27, 2017
@peleteiro
Copy link

peleteiro commented Nov 29, 2017

How should I create custom theme values/nodes? I could cast Theme while using it, but I don't see how can I create a custom theme the way it's mapped rigth now.

I'm a typescript newbie, so any help is appreciate.

I used to configure my theme this way:

import {indigo} from 'material-ui/colors'
import {createMuiTheme, Theme as MuiTheme} from 'material-ui/styles'
import createPalette from 'material-ui/styles/createPalette'

interface BBoxTheme {
  linkColor: string
  navbar: {
    title: {
      fontFamily: string
    }
  }
  bible: {
    fontFamily: string
  }
}

export type Theme = MuiTheme<BBoxTheme>

export default createMuiTheme<BBoxTheme>({
  palette: createPalette({
    primary: indigo,
    type: 'light',
  }),
  linkColor: '#2969b0',
  navbar: {
    title: {
      fontFamily: 'Helvetica, Arial, sans-serif',
    },
  },
  bible: {
    fontFamily: 'Lora, serif',
  },
})

@pelotom
Copy link
Member Author

pelotom commented Nov 29, 2017

See this comment and #9272. Basically, in TypeScript there is no way to make “custom themes” type safe, so it’s best to make that clear by requiring you to cast. But also ask yourself if you really need custom themes, or could you just export your custom variables from a module and import them where needed?

@pelotom pelotom deleted the unparameterize-theme branch November 29, 2017 15:37
@peleteiro
Copy link

peleteiro commented Nov 29, 2017

Theme as global does not work if you app runs on the server-side/isomorphic (my case) and we need to have some customization per-user. In this scenario theme as it is is really helpful. I seens to me that Theme with Parameterized type would be a better solution since it does not block you from using theme as global variable/require when suitable.

It seems pretty type safe. That how I use withStyle in my project:

import {StyleRules, withStyles, WithStyles} from 'material-ui/styles'
import * as React from 'react'
import {connect} from 'react-redux'
import {bindActionCreators, Dispatch} from 'redux'
import {Theme} from '../theme'

type ClassKey = 'container' | 'area' | 'menu'

const styles = (theme: Theme): StyleRules<ClassKey> => ({
  container: {...},
  area: {...},
  menu: {...},
})

class FooterContainer extends React.PureComponent<WithStyles<ClassKey> & ConnectedProps & ActionsProps> {
... 
}

export default withStyles(styles)(FooterContainer)

@pelotom
Copy link
Member Author

pelotom commented Nov 29, 2017

What's to stop you from doing this though:

const styles = (theme: Theme & { bogus: number }): StyleRules<ClassKey> => ({

that's the source of the unsafety.

@peleteiro
Copy link

peleteiro commented Nov 29, 2017

That would be fine, if createMuiTheme works. IMHO, we need a way to extend Theme, as it works with plain JS and Flow, I think TS should not change the way Material-ui works and theme (as in react-jss) can be extend.

I don't see how to extend theme, once createMuiTheme wont accept my extends.

I'm new to TS, any help is appreciate.

@rosskevin
Copy link
Member

I just added a doc to strongly type your theme through typescript module augmentation:
https://github.com/mui-org/material-ui/pull/9350/files

It will get merged into the Typescript guide in the docs.

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

Successfully merging this pull request may close these issues.

5 participants