0
votes

I m using styled components with React typescript. I have created a theme.ts where I define my variables that i use in my ThemeProvider to expose them to my application. In addition I have a styled.d.ts, where I declare my DefaultTheme that I use as an interface for theme.ts.

I have created a separate file. media.ts where I create reusable media queries as described in this article: https://medium.com/@samuelresua/easy-media-queries-in-styled-components-690b78f50053, and now I want to include ...media in my theme so I can use it with my theme:

media.ts

import { css } from 'styled-components'

interface MediaQueryProps {
    [key: string]: any;
  }
const breakpoints:  MediaQueryProps = {
   xs: 480,
   sm: 768,
   md: 992,
   lg: 1200 
}

export default Object.keys(breakpoints).reduce((acc, label) => {
   acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) => css`
      @media (max-width: ${breakpoints[label]}px) {
         ${css(literals, ...placeholders)};
      }
   `.join("");
   return acc
}, {}  as Record<keyof typeof breakpoints, (l: TemplateStringsArray, ...p: any[])=> string>)


theme.ts

import { DefaultTheme } from 'styled-components'
import media from './media';

const theme: DefaultTheme = {
    primary: "#262646",
    secondary: "#F9FAFE",
    success: "#00897B",
    danger: "#B00020",
    text: "#263646", 
    background: "#E8EAF6",
    white: "#ffffff",
    fonts: ["sans-serif", "Roboto"],
    ...media,
    fontSizes: {
      small: "1em",
      medium: "1.2em",
    },
  }  
  export default theme;

styled.d.ts

// import original module declarations
import 'styled-components'

// and extend them!
declare module 'styled-components' {
  export interface DefaultTheme {
    primary: string,
    secondary: string,
    success: string,
    danger: string,
    text: string, 
    background: string,
    white: string,
    fonts: Array<string>,
    fontSizes: {
      small: string,
      medium: string,
    },
  }
}

If I try to use my mediaqueries in my App.ts, without including ...media in DefaultTheme, it throws error 'Property 'media' does not exist on type 'DefaultTheme'.ts(2339)',

const TableRow = styled.tr`
    &:nth-of-type(odd){
        background: ${props => props.theme.secondary}
    }
    ${({theme}) => theme.media.sm`
        background: ${theme.secondary}
   `}
`

but if i define it as following it throws error

declare module 'styled-components' {
  export interface DefaultTheme {
    media: Array<string>
  }
} 

it throws and error in theme.ts 'Property 'media' is missing in type '{ primary: string; secondary: string; success: string; danger: string; text: string; background: string; white: string; fonts: string[]; fontSizes: { small: string; medium: string; }; }' but required in type 'DefaultTheme'.ts(2741)'

I m completely lost about how to define it in a right way for it to work. when I hover over media I get following information form typescript:

(alias) const media: Record string>

help pliz...

1

1 Answers

0
votes

I think your problem is that you defined a theme interface where you didn't defined the fields exported from media, but you are trying to use the them in the default theme, which type is Them which does not have the media fields.

The easiest way is to define a media filed in your interface, type any and put the media queries inside the media field. I am not sure if that work for you or if it's a good practice. I haven't work a lot with this type of theming, but I think something like this should do the job.