简体   繁体   English

如何使用 Typescript 扩展 Material-UI 主题?

[英]How to extend Material-UI Theme with Typescript?

Typescript is always complaining about certain properties missing in the palette. Typescript 总是抱怨调色板中缺少某些属性。 My app works just fine if I add //@ts-ignore , but I obviously want to avoid that.如果我添加//@ts-ignore ,我的应用程序工作得很好,但我显然想避免这种情况。 I'm new to Typescript and here is what I've tried.我是 Typescript 的新手,这是我尝试过的。

import createMuiTheme, { ThemeOptions, Theme } from '@material-ui/core/styles/createMuiTheme';
import { PaletteOptions } from '@material-ui/core/styles/createPalette';

interface IPaletteOptions extends PaletteOptions {
    chip: {
      color: string,
      expandIcon: {
        background: string,
        color: string,
      },
    },
}
interface ITheme extends Theme {
  palette: IPaletteOptions,
}

const theme: ITheme = createMuiTheme({
  typography: {
    fontWeightMedium: 600,
    fontFamily: ['Open Sans', 'Arial', 'sans-serif'].join(','),
  },
  palette: {
    primary: {
      main: '#43C099',
    },
    secondary: {
      main: '#7AF3CA',
    },
    chip: {
      color: '#C2C3C6',
      expandIcon: {
        background: '#808183',
        color: '#FFFFFF',
      },
    },
  },
} as ThemeOptions);

This throws an error,这会引发错误,

Type 'Theme' is not assignable to type 'ITheme'.
  Types of property 'palette' are incompatible.
    Property 'chip' is missing in type 'Palette' but required in type 'IPaletteOptions

This is a confusing error for me, because type I'm not using the type Palette anywhere.这对我来说是一个令人困惑的错误,因为类型我没有在任何地方使用类型Palette

How can I properly extend the palette here?我怎样才能在这里正确地扩展调色板?

This can be solved much easier via Module Augmentation :这可以通过Module Augmentation更容易地解决:

material-ui.d.ts

import { PaletteOptions } from "@material-ui/core/styles/createPalette";

declare module "@material-ui/core/styles/createPalette" {
  export interface PaletteOptions {
    chip: {
      color: string;
      expandIcon: {
        background: string;
        color: string;
      };
    };
  }
}

Solution解决方案

import createMuiTheme, { Theme, ThemeOptions } from "@material-ui/core/styles/createMuiTheme";
import { Palette } from "@material-ui/core/styles/createPalette";

interface IPalette extends Palette {
  xxx: {}
}
interface ITheme extends Theme {
  palette: IPalette;
}
interface IThemeOptions extends ThemeOptions {
  palette: IPalette;
}

const theme = createMuiTheme({
  palette: {
    ...
    xxx: {}                                        // Type been checked
  }
} as IThemeOptions)                                // Use customized ThemeOptions type

const useStyles = makeStyles((theme: ITheme) => ({ // Use customized Theme type
  root: {
    color: theme.palette.xxx                       // Work with no type error
  }
}));

Refer参考

If we look at the createMuiTheme.d.ts如果我们看一下createMuiTheme.d.ts

import { Palette, PaletteOptions } from './createPalette';

export interface ThemeOptions {
  palette?: PaletteOptions;
  ...
}

export interface Theme {
  palette: Palette;
  ...
}

export default function createMuiTheme(options?: ThemeOptions, ...args: object[]): Theme;

We would find that Theme and ThemeOptions play a different role.我们会发现ThemeThemeOptions扮演着不同的角色。

  • Theme: return type主题:返回类型
  • ThemeOptions: params type ThemeOptions:参数类型

In React typescript, you have to declare that the variable is a type of ThemeOptions when using the theme in the child component.在 React typescript 中,在子组件中使用主题时必须声明该变量是一种 ThemeOptions。

import { ThemeOptions } from '@mui/material';

const ChildComponent: React.FC<Props> = (Props) => {
const theme:ThemeOptions  = useTheme();
  const theme:ThemeOptions = React.useContext(ThemeContext); 
return ()}

This is how i'm extending in MUI v5这就是我在 MUI v5 中扩展的方式

import { PaletteColorOptions } from '@mui/material';

declare module '@mui/material/styles' {

  // add inside palette
  interface PaletteOptions {
    customStatus: PaletteColorOptions;
    colorDark: PaletteColorOptions;
    customDanger: PaletteColorOptions;
  }

  // customize inside palette.background
  interface TypeBackground {
    light: string;
  }

  // add inside theme
  // interface ThemeOptions {
  // }

}

// extend typography inside the theme
declare module '@mui/material/styles/createTypography' {
  interface FontStyle {
    font1: string;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM