Can't customize color palette types on Material UI theme in TypeScript

Viewed 10628

I create a type interface to add custom properties to the Palette like so:

declare module @material-ui/core/styles/createMuiTheme {
  interface PaletteColor {
    transparent?: string;
    gradient?: PaletteColor;
  }
  interface Palette {
    gradient?: PaletteColor;
    transparent?: PaletteColor;
    secondary?: {
      transparent?: string;
    }
  }

  interface PaletteColorOptions {
    main?:string;
    dark?:string;
    light?:string;
    transparent?: string;
    gradient?: string;
    test?: string
  }
}

I am trying to a lot of interfaces to get it to work...

Then I use those types in my theme like this:

export default function createMyTheme(options: ThemeOptions) {
    return createMuiTheme({
      ...options,
    })
  }

I use that function to create my main theme by importing it and calling it:

const theme = createMyTheme({});

And then I set my component style like this: background: theme.palette.gradient.main,

and it tells me this:

Property 'gradient' does not exist on type 'Palette'.

Environment: "@material-ui/core": "^4.9.2", "react": "^16.12.0", "typescript": "^3.7.5"

Here is my full theme:

const theme = createMyTheme({
  palette: {
    primary: {
      main: '#5FB9A6',
      dark: 'linear-gradient(-68deg, #151E27 , #335850)',
      gradient: 'linear-gradient(-68deg, #151E27 , #335850)'
    },
    secondary: {
      main: '#C68A77',
      transparent: 'rgba(198, 138, 119, 0.7)'
    },
    error: {
      light: '#e5a0a0',
      main: '#CD5C5C',
      dark: '#992c2c',
    },
    text: {
      primary:'#20383C',
      secondary: '#151E27',
      hint: 'rgba(32, 56, 60, 0.7)'
    },
    background: {
      paper: '#fff'
    },
    common: {
      white: "#FFF"
    }
  },
  typography: {
     fontFamily: '"Work Sans"'
  }

Any help would be greatly appreciated! Thanks!

4 Answers

According to the documentation you need module augmentation to add custom properties to the palette.

What I did was:

Created a file expanded-theme.ts in the root directory (same directory where App.tsx is)

import '@material-ui/core/styles';

declare module '@material-ui/core/styles/createPalette' {
  interface Palette {
    myCustomColor?: Palette['primary'];
  }
  interface PaletteOptions {
    myCustomColor?: PaletteOptions['primary'];
  }
}

Next, you can define the custom properties in your theme (I did not need to import expanded-theme.ts)

import React from 'react';
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core';

// ...

const theme = createMuiTheme({
  palette: {
    myCustomColor: {
      main: 'blue'
    }
  }
});

// ...

<MuiThemeProvider theme={theme}>

//...

Now you can use myCustomColor in your styles :).

For if I want a new custom color palette neutral , then this worked for me, :

Inside mui.d.ts in root of project

import "@mui/material/styles/createPalette";
declare module "@mui/material/styles/createPalette" {
  interface PaletteOptions {
    neutral: PaletteColorOptions;
  }
}

And put it in the include of tsconfig.json

...
"include": [... , mui.d.ts]
...

I'm trying to get this to work as well, and I'm missing something very fundamental. Where does code for declare module '@material-ui/core/styles/createMuiTheme' actually go? I tried creating a types.d.ts file, and then in my entry index.js file, I include it it like this: import './config/types.d';

...but I still get the same sort of type error you're getting. As for your above example, it looks like MUI's example has quotes around '@material-ui/core/styles/createMuiTheme', but your code does not. Also, their example shows actually importing the modules from MUI that are then modified. And finally, your code looks self-referential (e.g. the gradient definition in interface PaletteColor is also PaletteColor). I don't know if any of those things are actually problematic, though.

My types.d.ts file looks like this:

import { Palette } from '@material-ui/core/styles/createMuiTheme';
//https://material-ui.com/guides/typescript/#customization-of-theme
declare module '@material-ui/core/styles/createMuiTheme' {
  interface Palette {
    background: {
      appSubHead: string;
    };
  }

  interface PaletteOptions {
    background?: {
      appSubHead?: string;
    };
  }
}

I'm using material-ui with create-react-app and typescript. Importing Palette worked for me.

import { Palette } from '@material-ui/core/styles/createPalette'
Related