【问题标题】:Extending Material UI theme via Module Augmentation not working correctly通过模块增强扩展 Material UI 主题无法正常工作
【发布时间】:2021-03-02 15:12:01
【问题描述】:

我正在尝试使用 Material UI 扩展 Theme,但它抛出一个错误,说我没有正确扩展它,说,

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

这是我所拥有的:

// 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>;
});

我在这里做错了什么?我想在我的整个应用程序中使用ITheme,除了我添加的内容之外,这将扩展基本的Theme

【问题讨论】:

    标签: javascript reactjs typescript material-ui


    【解决方案1】:

    我认为覆盖使用您的 ITheme 的东西会更方便,如下所示:

    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;
    }
    

    那么您不再需要在 theme/index.ts 中转换返回的类型:

    export default createMuiTheme({ palette });
    

    如果使用useTheme,它应该按预期返回ITheme

    注意:我也更新了代码框:https://codesandbox.io/s/charming-pasteur-s6h8v?file=/src/Component.tsx

    【讨论】:

    • 感谢您的建议。另外,请注意,TS 仍在您的沙盒中抱怨 (Interface 'ITheme' incorrectly extends interface 'Theme'. Types of property 'palette' are incompatible. )
    • 这是您之前的设置。看起来新的palette IPaletteOptions 与当前的Theme["palette"] 不是100% 兼容。但我们可以通过像这样设置export type ITheme = Theme &amp; { palette: IPaletteOptions } 来修复。在此处查看新更改:codesandbox.io/s/charming-pasteur-s6h8v?file=/typings/…
    【解决方案2】:

    我通过使用这个来完成这个工作:

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

    注意“核心”不包含在模块中。

    我的完整代码:

    import theme from './theme';
    
    type CustomTheme = {
      palette: typeof theme;
    };
    
    declare module '@material-ui/styles' {
      export interface DefaultTheme extends CustomTheme {}
    }
    

    【讨论】:

      【解决方案3】:

      在 Material v5 中,您可以扩展 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
        }
      }));
      

      【讨论】:

        猜你喜欢
        • 2022-11-22
        • 1970-01-01
        • 2020-10-09
        • 1970-01-01
        • 2021-02-21
        • 2017-05-03
        • 1970-01-01
        • 1970-01-01
        • 2021-07-04
        相关资源
        最近更新 更多