MUI 커스텀 테마에 타입스크립트 적용
2022. 2. 26.
타입스크립트 환경에서 MUI 의 테마에 필드를 추가하려면 타입스크립트 또한 추가적인 타입 선언이 필요하다. 어떻게 하면 되는지 유형별로 간단히 살펴보자.
References
- MUI Docs
- StackOverflow Add property to background prop in createMuiTheme in Material-UI using Typescript
- GitHub mui/material-ui - createPalette.d.ts
1. 테마에 커스텀 필드 추가
테마에 기존에 존재하지 않는 새로운 필드를 추가할 수 있다.
const theme = createTheme({
status: {
danger: orange[500],
},
});
이것을 위한 타입스크립트 타입 선언은 경우에는 아래처럼 해주면 된다.
declare module "@mui/material/styles" {
interface Theme {
status: {
danger: string;
};
}
interface ThemeOptions {
status?: {
danger?: string;
};
}
}
2. 테마 Palette 에 커스텀 필드 추가
테마의 palatte 에 색상을 추가하면 color
, sx
prop 등에서 이름만으로 색상을 지정할 수 있게 된다. 아래 코드처럼 palette.neutral
을 추가한다면,
const theme = createTheme({
palette: {
neutral: {
main: "#64748B",
contrastText: "#fff",
},
},
});
타입스크립트는 아래처럼 해주면 된다.
declare module "@mui/material/styles" {
interface Palette {
neutral: Palette["primary"];
}
interface PaletteOptions {
neutral: PaletteOptions["primary"];
}
}
이걸로 끝이면 좋겠지만, 특정 컴포넌트의 color
속성에서도 위에서 추가한 색상을 쓰고 싶다면, 해당 컴포넌트에 관한 타입 추가 선언을 해주어야 한다.
// Button 의 color prop 에서 neutral 을 쓰고 싶을 경우
declare module "@mui/material/Button" {
interface ButtonPropsColorOverrides {
neutral: true;
}
}
3. 테마 Palette 의 특정 색상에 필드 추가
Palette 의 특정 색상에 필드를 추가하고 싶을 수 있다. 아래는 palette.primary.darker
, palette.background.contrastText
를 추가했다.
const normalTheme = createTheme({
palette: {
primary: {
main: "#0971f1",
darker: "#053e85",
},
background: {
default: "#E4E7EB",
contrastText: "#000000",
},
},
});
속성을 추가하려는 색상이 primary
, secondary
, error
, warning
, info
, success
중 하나라면, 이 색상들은 타입을 공유하기 때문에 아래처럼 타입을 지정하면 된다.
declare module "@mui/material/styles" {
interface PaletteColor {
darker?: string;
}
interface SimplePaletteColorOptions {
darker?: string;
}
}
하지만 background
의 경우 다른 타입을 사용하므로 아래처럼 해주어야 한다.
declare module "@mui/material/styles/createPalette" {
interface TypeBackground {
default: string;
paper: string;
contrastText: string;
}
}
어떤 색상이 어떤 타입을 사용하는지 알고 싶다면 createPalette.d.ts 코드를 보면 된다. 아래처럼 나와있으니 참고해서 타입 지정을 해주면 된다.
export interface PaletteOptions {
primary?: PaletteColorOptions;
secondary?: PaletteColorOptions;
error?: PaletteColorOptions;
warning?: PaletteColorOptions;
info?: PaletteColorOptions;
success?: PaletteColorOptions;
mode?: PaletteMode;
tonalOffset?: PaletteTonalOffset;
contrastThreshold?: number;
common?: Partial<CommonColors>;
grey?: ColorPartial;
text?: Partial<TypeText>;
divider?: string;
action?: Partial<TypeAction>;
background?: Partial<TypeBackground>;
getContrastText?: (background: string) => string;
}