Stevetro
Stevetro

Reputation: 1963

declaration merging for react-native-elements theme

I am using react-native-elements in my react-native application.

My app is wrapped with the ThemeProvider to pass the theme down to all components.

<SafeAreaProvider>
 <ThemeProvider theme={Theme}>
    <Loader visible={loader.loading} text={loader.message} absolute={true} />
    <RootNavigation />
  </ThemeProvider>
</SafeAreaProvider>

In the theme file i define the values i want to use across the app.

const theme = {
  colors: {
    primary: '#6A69E2',
    primaryDark: '#4747c2',
    primaryLight: 'rgba(106, 105, 226, 0.35)',
    gray: {
      dark: '#242424',
      default: '#666',
      medium: '#999',
      light: '#ccc',
      lightest: '#e7e7e7',
    },
  },
  text: {
    size: {
      small: 12,
      default: 16,
      large: 18,
      h1: 26,
      h2: 22,
      h3: 20,
    },
  },
  Text: {
    style: {
      fontSize: 16,
      color: '#242424',
      fontFamily: 'Roboto',
    },
  },
  Button: {
    style: {
      borderRadius: 50,
    },
    disabledStyle: {
      backgroundColor: 'rgba(106, 105, 226, 0.35)',
    },
  },
};

export default theme;

For the values the original theme of react-native-elements providing this is working. For example i can access the colors by using

const theme = useTheme()
theme.colors.primary

But when i want to add some new properties like primaryDark i'll get an linter error.

Object literal may only specify known properties, and 'primaryDark' does not exist in type 'RecursivePartial<Colors>'.ts(2322)

In the doc of react-native-elements is a part about declaration merging, but i don't understand how i can archive this https://reactnativeelements.com/docs/customization/#typescript-definitions-extending-the-default-theme.

Somebody could help me with this?

Upvotes: 1

Views: 953

Answers (1)

hackape
hackape

Reputation: 19957

Well, declaration merging still works. This seems like a bug on the lib's part.

Their doc says you can augment the Color interface in module 'react-native-elements'. But currently (as of 2021-04-18, with v3.3.2) that interface is actually hidden inside module 'react-native-elements/dist/config/colors', not directly exposed at the top level, weird.

I suggest you file an issue to their repo. Never mind, someone already filed the issue.

Tested on my machine, following solution works.

import React from 'react'
import { useTheme, ThemeProvider } from 'react-native-elements'

declare module 'react-native-elements/dist/config/colors' {
  export interface Colors {
    primaryDark: string
    primaryLight: string
  }
}

const ChildComp = () => {
  const theme = useTheme()
  theme.theme.colors.primaryDark // <-- No more error 🎉
  return <div>foobar</div>
}

Reply to OP's comment. You can augment interface however you like, as long as the augmented key doesn't exist before. For example add foobar key to FullTheme.

declare module 'react-native-elements' {
  export interface FullTheme {
    foobar: string
  }
}

Upvotes: 4

Related Questions