javascript - Att utöka Material UI-temat via modulförstärkning fungerar inte korrekt
Jag försöker utöka Theme med Material UI, men det ger ett fel och säger att jag inte utökar det korrekt, och säger,
Property 'layout' is missing in type 'Palette' but required in type 'IPaletteOptions'.
Här är vad jag har:
// 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>;
});
Vad gör jag fel här? Jag skulle vilja använda ITheme i hela min app, vilket skulle utöka den grundläggande Theme utöver det jag lägger till.
Svar #1
I Material v5 kan du utöka 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
}
}));
Svar #2
Jag funderar på att det skulle vara ännu smidigare att åsidosätta saker som använder ditt ITheme på följande sätt:
theme.d.tsdeclare 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;
}
Då behöver du inte längre göra typomvandling på det returnerade värdet i din theme/index.ts:
export default createMuiTheme({ palette });
Vid användning av useTheme bör det returnera ITheme som förväntat.
OBS: Jag har också uppdaterat codesandbox: https://codesandbox.io/s/charming-pasteur-s6h8v?file=/src/Component.tsx