React Typescript: property 'body' does not exist type 'DefaultTheme'

Viewed 8818

I am new to React and Typescript, I am trying to add dark-mode to my project, I created globalStyle component, Themes component and using Themeprovider.

I am facing an issue on my globalStyle component when it says: property 'body' does not exist type 'DefaultTheme'

My globalStyles.tsx code is as follow:

import { createGlobalStyle} from "styled-components"
export const GlobalStyles = createGlobalStyle`
  body {
    background: ${({ theme }) => theme.body};
    color: ${({ theme }) => theme.text};
    font-family: Tahoma, Helvetica, Arial, Roboto, sans-serif;
    transition: all 0.50s linear;
  }`

my Themes.tsx:

export const lightTheme = {
    body: '#FFF',
    text: '#363537',
    background: '#363537',
}
export const darkTheme = {
    body: '#363537',
    text: '#FAFAFA',
    background: '#999',
}

and my Themeprovider code on App.tsx:

<ThemeProvider theme={this.state.theme === 'light' ? lightTheme : darkTheme}>
        <>
        <GlobalStyles/>
            <ul className='tickets'>
                {filteredTickets.map((ticket) => (
                <li key={ticket.id} className={ticket.toggle ? 'expand' : 'ticket'}>
                    <h5 className='title'>{ticket.title}</h5>
                    <button onClick={() => this.onHide(ticket.id)}>Hide</button>
                    <p className={ticket.toggle ? 'show-more' : 'content'}>{ticket.content}</p>
                    <button onClick={()=> this.onToggle(ticket.id)}>{ticket.toggle ? 'Show less' : 'Show more'}</button>
                    <footer>
                        <div className='meta-data'>By {ticket.userEmail} | { new Date(ticket.creationTime).toLocaleString()}</div>
                    </footer>
                </li>))}
            </ul>
        </>
        </ThemeProvider>

What am I doing wrong and why theme.body and theme.text is not recognized on globalStyles.tsx?

Thanks !

2 Answers

I'm basing this answer on the following link: https://spectrum.chat/styled-components/general/i-cant-use-my-theme-in-createglobalstyle-function-styled-components-v4-react-v16-6-3~0978b404-ab71-45c9-8f75-0862abde4eb5

createGlobalStyle can accept a shape for the theme:

createGlobalStyle<{theme: ThemeType}>

From the styled-components docs, there's this (https://styled-components.com/docs/api#typescript):

declare module 'styled-components' {
  export interface DefaultTheme {
    borderRadius: string;

    colors: {
      main: string;
      secondary: string;
    };
  }
}

So, I suggest you set up an interface for your theme, as above, and then pass it into createGlobalStyle in place of ThemeType

So the answer above fails, as useTheme does not know what type you passed to createGlobalStyles.

But this is a typescript workaround that doesn't require you to use ts-ginore:

  1. As jnpdx suggested, you do need to type the createGlobalTheme object:

createGlobalStyle<{theme: ThemeType}>

  1. The only working solution I have figured out so far is to post-type your useTheme variable like so:

const theme = useTheme() as ThemeType;

Related