Search code examples
typescriptreact-nativetypesstyled-components

React-Native-Styled-Components: Property 'backgroundColor' does not exist on type 'DefaultTheme'


I am using react-native-Typescript for my app. My styled-components version is "styled-components": "^5.3.0". I have create custom ThemeProvider and wrap to my root app. I have have toggle dark theme for my app. My ThemeProvider works fine. I can able to make DarkTheme and LightTheme. But when I am testing my apps Typescript by using this command yarn tsc. I am getting typescript error: error TS2339: Property 'backgroundColor' does not exist on type 'DefaultTheme'.. In styled-components it says Create a declarations file, but it was for version: v4.1.4. And I am using "^5.3.0"`. I really don't how to silent this Typescript Error.

This is my Theme Colors and it's types

export interface Theme {
  backgroundColor: string;
  primary: string;
  text: string;
  error: string;
}

export const lightTheme: Theme = {
  backgroundColor: '#FFFFFF',
  primary: '#512DA8',
  text: '#121212',
  error: '#D32F2F',
};

export const darkTheme: Theme = {
  backgroundColor: '#121212',
  primary: '#B39DDB',
  text: '#FFFFFF',
  error: '#EF9A9A',
};

export type TTheme = typeof lightTheme;

This is my Theme Provider

import React, {useState, useEffect, useCallback, createContext} from 'react';
import {ThemeProvider as SCProvider} from 'styled-components/native';

import {lightTheme, darkTheme} from 'local/theme'; // I am imported the theme


interface ThemeContext {
  theme: string;
  toggleTheme: (value: string) => void;
}

interface ThemeProviderProps {
  children: JSX.Element;
}

export const ThemeContext = createContext<ThemeContext>({} as ThemeContext);

const ThemeProvider = ({children}: ThemeProviderProps) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = (value: string) => {
    if (value) {
      setTheme(value);

    }
  };

  const checkForLocalThemeSetting = useCallback(async () => {
    if (localTheme && localTheme !== theme) {
      setTheme(localTheme);
    }
  }, [theme]);

  useEffect(() => {
    checkForLocalThemeSetting();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <ThemeContext.Provider value={{theme, toggleTheme}}>
      <SCProvider theme={theme === 'dark' ? darkTheme : lightTheme}>
        {children}
      </SCProvider>
    </ThemeContext.Provider>
  );
};

export default ThemeProvider;

This is warp my Theme Provider to my root project

  <NavigationContainer>
      <StatusBar barStyle="dark-content" />
      <SafeAreaProvider>
        <LocalizationProvider>
          <ThemeProvider>
            <Tab.Navigator>
              <Tab.Screen name="Home" component={HomeScreen} />
              <Tab.Screen name="Settings" component={SettingsScreen} />
            </Tab.Navigator>
          </ThemeProvider>
        </LocalizationProvider>
      </SafeAreaProvider>
    </NavigationContainer>

In this component I am testing my light and dark

import React, {useContext} from 'react';
import {ScrollView, StyleSheet, Text, Switch} from 'react-native';

import styled from 'styled-components/native';

import {ThemeContext} from 'local/providers/ThemeProvider';


const Home = () => {

  const {theme, toggleTheme} = useContext(ThemeContext);


  return (
    <ScrollView>
      <Wrapper
        style={{}>
        <Text >Hello world</Text>
      </Wrapper>
      <Switch
        trackColor={{false: '#767577', true: '#81b0ff'}}
        thumbColor={theme === 'dark' ? '#f5dd4b' : '#f4f3f4'}
        ios_backgroundColor="#3e3e3e"
        onValueChange={i => {
          if (i) {
            toggleTheme('dark');
          } else {
            toggleTheme('light');
          }
        }}
        value={theme === 'dark'}
      />
    </ScrollView>
  );
};

const Wrapper = styled.View`
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: ${({theme}) => theme.backgroundColor}; // Typescript error: error TS2339: Property 'backgroundColor' does not exist on type 'DefaultTheme'.
`;


export default Home;

Solution

  • You need to create declarations file for initialisation you DefaultTheme types as in the documentation. Right now you have a type interface Theme but styled-component doesn't know about it. In that case must declare type in the styled-component. Try add this the snippet in your Theme colors types. react.js example

    import {DefaultTheme} from 'styled-components/native';
    
    declare module "styled-components" {
      export interface Theme {
        backgroundColor: string;
        primary: string;
        text: string;
        error: string;
      }
    }
    
    export const lightTheme: DefaultTheme = {
      backgroundColor: "#FFFFFF",
      primary: "#512DA8",
      text: "#121212",
      error: "#D32F2F"
    };
    
    export const darkTheme: DefaultTheme = {
      backgroundColor: "#121212",
      primary: "#B39DDB",
      text: "#FFFFFF",
      error: "#EF9A9A"
    };