Emotion: Typescript ThemeProvider + Props

Created on 15 Aug 2018  路  5Comments  路  Source: emotion-js/emotion

Hello,

Does anyone know of a way to use TypeScript with ThemeProvider & Props?

I have a ThemeProvider like

export default {
  color: {
    blue: 'blue'
  }
}

And then I have a component

type Props = {
  outline?: boolean;
  theme?: any;
}

const Button = styled('button')((props: Props) => ({
   color: props.theme.color.blue,
   background: props.outline ? '#fff' : props.theme.color.blue
})

And this works but obviously theme?: any; won't have any typescript benefits. Is there a way to combine custom properties and the passed in themeprovider props?

I've been through https://emotion.sh/docs/typescript and none of those are what I want to do.

TypeScript question

Most helpful comment

Following will help you.
https://emotion.sh/docs/typescript#define-a-theme
However, to use custom props, you should pass generic parameter instead of annotate type to function argument (since type annotation will hide the props.theme because your Props type does not explicitly have theme in it).

styled('button')<Props>((props) => /*...*/)

All 5 comments

Following will help you.
https://emotion.sh/docs/typescript#define-a-theme
However, to use custom props, you should pass generic parameter instead of annotate type to function argument (since type annotation will hide the props.theme because your Props type does not explicitly have theme in it).

styled('button')<Props>((props) => /*...*/)

Hi y'all,

do you know how material-ui is doing that? They have an interface Theme which is used for example in withTheme and you can use Typescripts module augmentation to add your stuff to the Theme. Is there any reason against that?

declare module '@material-ui/core/styles/createMuiTheme' {
  interface Theme {
    appDrawer: {
      width: React.CSSProperties['width']
      breakpoint: Breakpoint
    }
  }
}

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

In addition to the comment by @Ailrun, you can do something like

type StyledProps<T = {}> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement> & Partial<T>, HTMLDivElement>;

and

interface MyComponentProps {
    myprop: 'blue' | 'red';
}

const MyStyledElement = styled.div<StyledProps<MyComponentProps>>`
    color: ${ props => props.myprop };
`;

Then your element can take a partial of your component props

const MyComponent: React.StatelessComponent<MyComponentProps> = (props) => (
     <div>
         <MyStyledElement { ...props } />
     </div>
);

Just an idea.

I'd appreaciate solution as provided by MUI or styled-components (using module augmentation).

There is a more recent discussion about this in https://github.com/emotion-js/emotion/issues/1507 . Closing this one in favor of the other one, hope you understand.

Was this page helpful?
0 / 5 - 0 ratings