最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Extending Material UI theme via Module Augmentation not working correctly - Stack Overflow

programmeradmin0浏览0评论

I'm trying to extend Theme with Material UI, but it's throwing an error, saying that I'm not extending it correctly, saying,

Property 'layout' is missing in type 'Palette' but required in type 'IPaletteOptions'.

Here is what I have:

// src/theme/theme.d.ts
import { Theme } from "@material-ui/core/styles";
import {
  IPaletteOptions,
  PaletteOptions
} from "@material-ui/core/styles/createPalette";

type TLayout = {
  primary: string;
  secondary: string;
};

declare module "@material-ui/core/styles/createPalette" {
  export interface IPaletteOptions extends PaletteOptions {
    layout: TLayout;
  }
}

declare module "@material-ui/core/styles" {
  export interface ITheme extends Theme {
    palette: IPaletteOptions;
  }
}
// src/theme/index.ts
import { createMuiTheme, ITheme } from "@material-ui/core/styles";
import { IPaletteOptions } from "@material-ui/core/styles/createPalette";

export const palette = {
  layout: {
    primary: "#ffffff",
    secondary: "#e4e4e4"
  }
} as IPaletteOptions;

export default createMuiTheme({ palette }) as ITheme;
// src/App.tsx
import React from "react";
import { ThemeProvider, ITheme } from "@material-ui/core";
import theme from "./theme";

import Component from "./Component";

export default function App() {
  return (
    <ThemeProvider<ITheme> theme={theme}>
      <Component />
    </ThemeProvider>
  );
}
import { useTheme } from "@material-ui/core";
import React from "react";

export default React.memo(() => {
  const theme = useTheme(); // <-- this should be of type `ITheme` automatically
                            // If I do useTheme<ITheme>(), it shows property 'layout', but
                            // I shouldn't have to do that, because of the type casting that
                            // I do in App.tsx, where I import and use 'theme' from src/theme/index.ts

  return <div>the layout primary color is {theme.palette.layout.primary}</div>;
});

What am I doing wrong here? I would like to use ITheme throughout my app, which would extend the basic Theme in addition to what I add.

I'm trying to extend Theme with Material UI, but it's throwing an error, saying that I'm not extending it correctly, saying,

Property 'layout' is missing in type 'Palette' but required in type 'IPaletteOptions'.

Here is what I have:

// src/theme/theme.d.ts
import { Theme } from "@material-ui/core/styles";
import {
  IPaletteOptions,
  PaletteOptions
} from "@material-ui/core/styles/createPalette";

type TLayout = {
  primary: string;
  secondary: string;
};

declare module "@material-ui/core/styles/createPalette" {
  export interface IPaletteOptions extends PaletteOptions {
    layout: TLayout;
  }
}

declare module "@material-ui/core/styles" {
  export interface ITheme extends Theme {
    palette: IPaletteOptions;
  }
}
// src/theme/index.ts
import { createMuiTheme, ITheme } from "@material-ui/core/styles";
import { IPaletteOptions } from "@material-ui/core/styles/createPalette";

export const palette = {
  layout: {
    primary: "#ffffff",
    secondary: "#e4e4e4"
  }
} as IPaletteOptions;

export default createMuiTheme({ palette }) as ITheme;
// src/App.tsx
import React from "react";
import { ThemeProvider, ITheme } from "@material-ui/core";
import theme from "./theme";

import Component from "./Component";

export default function App() {
  return (
    <ThemeProvider<ITheme> theme={theme}>
      <Component />
    </ThemeProvider>
  );
}
import { useTheme } from "@material-ui/core";
import React from "react";

export default React.memo(() => {
  const theme = useTheme(); // <-- this should be of type `ITheme` automatically
                            // If I do useTheme<ITheme>(), it shows property 'layout', but
                            // I shouldn't have to do that, because of the type casting that
                            // I do in App.tsx, where I import and use 'theme' from src/theme/index.ts

  return <div>the layout primary color is {theme.palette.layout.primary}</div>;
});

What am I doing wrong here? I would like to use ITheme throughout my app, which would extend the basic Theme in addition to what I add.

Share Improve this question edited Nov 19, 2020 at 22:10 Mike K asked Nov 19, 2020 at 9:11 Mike KMike K 6,49117 gold badges75 silver badges143 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 8

In Material v5 you can extend CommonColors

declare module "@mui/material/styles/createPalette" {
  interface CommonColors {
    layout: {
      offBlack: string;
      offWhite: string;
    }
  }
}

const colors = createTheme({
  palette: {
    common: {
      layout: {
        offBlack: "#14142B",
        offWhite: "#FCFCFC",
      },
    },
  },
});

// In a component
const useStyles = makeStyles((theme) => ({
  target: {
    backgroundColor: theme.palette.common.layout.offBlack
  }
}));

I'm thinking of it would be even handy to override things which uses your ITheme like as following:

theme.d.ts

declare module "@material-ui/core/styles" {
  export interface ITheme extends Theme {
    palette: IPaletteOptions;
  }
  
  // Keep overriding these things in your app
  // In this case returns `ITheme`
  export function createMuiTheme(options?: ThemeOptions, ...args: object[]): ITheme;
  
  // returns `ITheme`
  export function useTheme<T = ITheme>(): T;
}

Then you no longer need to cast returned type anymore in your theme/index.ts:

export default createMuiTheme({ palette });

In case of using useTheme, it's supposed to return ITheme as expected.

NOTE: I've also updated the codesandbox as well: https://codesandbox.io/s/charming-pasteur-s6h8v?file=/src/Component.tsx

I got this working by using this:

declare module '@material-ui/styles' {
  export interface DefaultTheme extends CustomTheme {}
}

Notice 'core' is not included in the module.

My full code:

import theme from './theme';

type CustomTheme = {
  palette: typeof theme;
};

declare module '@material-ui/styles' {
  export interface DefaultTheme extends CustomTheme {}
}
发布评论

评论列表(0)

  1. 暂无评论