You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传递返回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类型:

  1. 修改父组件的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} />
}
  1. 同步调整子组件的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 08:21:57