MUI v5自定义Button变体出现TS2322类型不匹配报错如何解决
问题复现代码
在MUI v5中尝试扩展Button组件的自定义变体,编写代码如下:
declare module "@mui/material/Button" { interface ButtonPropsVariantOverrides { icon: true; iconOnly: true; } } const muiButton = { MuiButton: { variants: [ { props: { variant: "icon" }, style: { background: palette.primary.main, }, }, ], }, }; createTheme({ components: { ...muiButton } })
报错信息
TS编译抛出如下错误:
TS2322: Type '{ MuiButton: { styleOverrides: { root: { fontStyle: string; fontSize: number; fontWeight: number; color: string; minWidth: string; borderRadius: number; "text-transform": string; boxShadow: string; "&.Mui-disabled": { ...; }; }; outlined: { ...; }; sizeSmall: { ...; }; sizeMedium: { ...; }; sizeLarge: { ...; }; }; v...' is not assignable to type 'Components<BaseTheme>'. The types of 'MuiButton.variants' are incompatible between these types. Type '({ props: { variant: string; size?: undefined; }; style: { background: string; color: string; "& .MuiSvgIcon-root": { height: number; }; "&.MuiButton-icon": { paddingRight: number; paddingLeft: number; }; ... 8 more ...; "&.Mui-disabled": { ...; }; }; } | { ...; } | { ...; } | { ...; })[]' is not assignable to type '{ props: Partial<ButtonProps<"button", {}>>; style: Interpolation<{ theme: Theme; }>; }[]'. // 省略部分重复调用栈信息 The types of 'props.variant' are incompatible between these types.
核心错误提示:Type 'string' is not assignable to type '"icon" | "iconOnly" | "text" | "outlined" | "contained" | undefined'
错误截图参考:
报错原因
该问题是TypeScript的字面量类型拓宽特性导致的:
将MUI组件配置抽离为独立的muiButton变量时,TS在没有上下文类型约束的情况下,会把对象里的字符串值"icon"自动推断为宽泛的string类型,而非精确的字面量类型"icon"。但MUI内部的类型定义要求variant属性必须是内置变体+自定义变体组成的字面量联合类型,宽泛的string类型无法满足该类型约束,就会抛出类型不匹配错误。
修复方案
任选以下一种方案即可解决问题:
- 添加
as const断言阻止类型拓宽
给字面量值或者整个配置对象加as const,强制TS将值推断为精确的字面量类型:const muiButton = { MuiButton: { variants: [ { props: { variant: "icon" }, style: { background: palette.primary.main, }, }, ], }, } as const; // 可在整个对象外加as const,也可单独给"icon"值后加as const - 不抽离配置,直接写入
createTheme参数
直接把组件配置写在createTheme的入参中,TS会自动根据createTheme的参数类型做上下文类型推断,不会发生类型拓宽:createTheme({ components: { MuiButton: { variants: [ { props: { variant: "icon" }, style: { background: palette.primary.main, }, }, ], }, }, }) - 给抽离的配置显式标注类型
导入MUI提供的组件配置类型,给抽离的变量显式添加类型注解,TS会直接按照要求的类型校验属性值,不会出现拓宽问题:import type { Components } from '@mui/material/styles'; const muiButton: Components = { MuiButton: { variants: [ { props: { variant: "icon" }, style: { background: palette.primary.main, }, }, ], }, };
注意:请确保模块类型扩展代码(即
declare module "@mui/material/Button"部分)被包含在tsconfig的include配置范围内,否则自定义变体的类型扩展不会生效。
内容的提问来源于stack exchange,提问作者Jamie Hutber
相关产品推荐
相关产品推荐

