传递返回SX样式的函数作为Prop时的TypeScript错误解决
解决MUI中传递Sx回调函数给子组件的TypeScript类型错误
问题场景
父组件传递生成样式的函数给子组件修改Box样式,代码可正常运行但触发TypeScript类型错误:
父组件代码
const getSxProp: SxProps<Theme> = (theme: Theme) => ({ mt: 1, '.My-CSS-to-overwrite': { padding: '12px 16px 8px 16px', }, }); export const ParentComponent = () => { return <ChildComponent sxProp={getSxProp} /> }
子组件代码
type ChildComponentProps = { sxProp?: (theme: Theme) => SxProps<Theme>; }; export const ChildComponent = ({ sxProp }: ChildComponentProps) => { return ( <Box sx={theme => { if (sxProp) { return sxProp(theme); } return null; }}> <div>Some content</div> </Box> ); };
TypeScript错误信息
No overload matches this call. Overload 1 of 2, '(props: { component: ElementType<any>; } & SystemProps<Theme> & { children?: ReactNode; component?: ElementType<any>; ref?: Ref<unknown>; sx?: SxProps<...>; } & CommonProps & Omit<...>): Element', gave the following error. Type '(theme: Theme) => SxProps<Theme>' is not assignable to type 'SxProps<Theme> | undefined'. Type '(theme: Theme) => SxProps<Theme>' is not assignable to type '(theme: Theme) => SystemStyleObject<Theme>'. Type 'SxProps<Theme>' is not assignable to type 'SystemStyleObject<Theme>'. Type '(theme: Theme) => SystemStyleObject<Theme>' is not assignable to type 'SystemStyleObject<Theme>'. Overload 2 of 2, '(props: DefaultComponentProps<BoxTypeMap<{}, "div">>): Element', gave the following error. Type '(theme: Theme) => SxProps<Theme>' is not assignable to type 'SxProps<Theme> | undefined'.ts(2769)
错误原因
MUI的SxProps<Theme>允许三种形式:SystemStyleObject<Theme>、(theme: Theme) => SystemStyleObject<Theme>、或数组组合。但子组件传递给Box.sx的回调函数返回的是SxProps<Theme>(可能嵌套另一个函数),超出了Box.sx要求的回调返回值类型(必须是SystemStyleObject<Theme>),导致类型不匹配。
解决方案
方案一:简化类型定义(推荐)
直接让样式函数返回SystemStyleObject<Theme>,避免嵌套SxProps类型:
- 修改父组件的
getSxProp类型:
// 指定返回值为SystemStyleObject,而非SxProps const getSxProp = (theme: Theme): SystemStyleObject<Theme> => ({ mt: 1, '.My-CSS-to-overwrite': { padding: '12px 16px 8px 16px', }, }); export const ParentComponent = () => { return <ChildComponent sxProp={getSxProp} /> }
- 同步调整子组件的props类型和sx逻辑:
import { SystemStyleObject, Theme, Box } from '@mui/material'; type ChildComponentProps = { sxProp?: (theme: Theme) => SystemStyleObject<Theme>; }; export const ChildComponent = ({ sxProp }: ChildComponentProps) => { return ( <Box sx={theme => sxProp?.(theme) ?? {}}> {/* 用空对象替代null,符合样式默认值要求 */} <div>Some content</div> </Box> ); };
方案二:兼容完整SxProps灵活性
如果需要保留SxProps的全部特性(如传递样式对象、数组或嵌套函数),可在子组件中手动解析SxProps:
import { useTheme, Theme, Box, SxProps, SystemStyleObject } from '@mui/material'; type ChildComponentProps = { sxProp?: SxProps<Theme>; }; // 递归解析SxProps为最终的SystemStyleObject const resolveSx = (sx: SxProps<Theme>, theme: Theme): SystemStyleObject<Theme> => { if (typeof sx === 'function') { const result = sx(theme); return typeof result === 'function' ? resolveSx(result, theme) : result; } return Array.isArray(sx) ? sx.flatMap(item => resolveSx(item, theme)) : sx ?? {}; }; export const ChildComponent = ({ sxProp }: ChildComponentProps) => { const theme = useTheme(); return ( <Box sx={resolveSx(sxProp, theme)}> <div>Some content</div> </Box> ); };
说明
方案一代码简洁,适合大多数场景;方案二保留SxProps全部灵活性,适合传递复杂样式组合的场景。
内容的提问来源于stack exchange,提问作者Mabeh Al-Zuq Yadeek
相关产品推荐
相关产品推荐

