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

如何结合TanStack/Router与MUI创建类型安全的路由参数链接

问题场景

在使用MUI Link组件跳转带参数的TanStack Router路由时,出现编译错误:

Type '{ itemId: string; }' is not assignable to type 'Omit<never, never>'

组件功能正常,但无法通过TypeScript类型检查。

相关代码示例

目标路由定义

export const itemViewRoute = new Route({
  getParentRoute: () => rootRoute,
  path: 'item/$itemId/view',
  component: ViewItem
});

export function ViewItem(){
  const params = useParams({from: itemViewRoute.id})
  return <>
    <SmallContentMain>
      <ContainerCard title={`View Item ${params.itemId}`}>
        <TextSpan>Description: "description of {params.itemId}"</TextSpan>
      </ContainerCard>
    </SmallContentMain>
  </>
}

正常工作的TanStack RouterLink

<ListItem>
  <RouterLink to={itemViewRoute.to}
    params={{itemId: "42"}} search={{}}
  >
    View Item 42 (RouterLink)
  </RouterLink>
</ListItem>

报错的MUI Link用法

<ListItem>
  <MuiLink component={RouterLink}
    to={itemViewRoute.to}
    preload={'intent'}
    search={{}} params={{itemId: '42'}}
  >
    View Item 42 (MuiLink)
  </MuiLink>
</ListItem>

完整错误信息

src/Route/Home.tsx:35:13 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(props: { component: LinkComponent<{}>; } & Omit<TypographyOwnProps, "children" | "classes" | "color" | "variant"> & { children?: ReactNode; ... 5 more ...; variant?: OverridableStringUnion<...> | undefined; } & CommonProps & Omit<...>): Element | null', gave the following error.
    Type '{ itemId: string; }' is not assignable to type 'ParamsReducer<{ itemId?: string | undefined; } & Record<never, string> & Record<"itemId", string>, { itemId?: string | undefined; } & Partial<{}> & Omit<never, never> & Partial<...> & Partial<...>>'.
      Type '{ itemId: string; }' is not assignable to type '{ itemId?: string | undefined; } & Partial<{}> & Omit<never, never> & Partial<Record<never, string>> & Partial<Record<never, string> & Record<...>>'.
        Type '{ itemId: string; }' is not assignable to type 'Omit<never, never>'.
          Property 'itemId' is incompatible with index signature.
            Type 'string' is not assignable to type 'never'.
  Overload 2 of 2, '(props: DefaultComponentProps<LinkTypeMap<{}, "a">>): Element | null', gave the following error.
    Type '{ children: string; component: LinkComponent<{}>; to: "/item/$itemId/view"; preload: string; search: {}; params: { itemId: string; }; }' is not assignable to type 'IntrinsicAttributes & Omit<TypographyOwnProps, "children" | "classes" | "color" | "variant"> & { children?: ReactNode; ... 5 more ...; variant?: OverridableStringUnion<...> | undefined; } & CommonProps & Omit<...>'.
      Property 'component' does not exist on type 'IntrinsicAttributes & Omit<TypographyOwnProps, "children" | "classes" | "color" | "variant"> & { children?: ReactNode; ... 5 more ...; variant?: OverridableStringUnion<...> | undefined; } & CommonProps & Omit<...>'.

 35             <MuiLink component={RouterLink}
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 36               to={itemViewRoute.to}
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 38               search={{}} params={{itemId: '42'}}
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 39             >
    ~~~~~~~~~~~~~

  node_modules/@tanstack/router-core/build/types/link.d.ts:61:5
    61     params: ParamsReducer<TFromFullParams, TToFullParams>;
           ~~~~~~
    The expected type comes from property 'params' which is declared here on type 'IntrinsicAttributes & { component: LinkComponent<{}>; } & Omit<TypographyOwnProps, "children" | "classes" | "color" | "variant"> & { ...; } & CommonProps & Omit<...>'


Found 1 error in src/Route/Home.tsx:35


Process finished with exit code 2

当前已配置的主题集成代码

export const LinkBehavior = React.forwardRef<
  HTMLAnchorElement,
  Omit<RouterLinkProps, 'to'> & { href: RouterLinkProps['to'] }
>((props, ref) => {
  const { href, ...other } = props;
  // Map href (Material UI) -> to (react-router)
  return <RouterLink ref={ref} to={href} {...other} />;
});

const muiLightTheme = createTheme({
  components: {
    MuiLink: {
      defaultProps: {
        component: LinkBehavior,
      } as RouterLinkProps,
    },
    MuiButtonBase: {
      // should be something like `as RouteButtonProps`?
      defaultProps: {
        LinkComponent: LinkBehavior,
      },
    },
...

版本信息

"@mui/material": "5.14.7",
"@tanstack/react-router" : "0.0.1-beta.185"

解决方案

1. 自定义带类型的MUI Link组件

创建封装组件,显式合并MUI Link与TanStack RouterLink的属性类型,让TypeScript正确识别路由参数:

import { Link as MuiLink, LinkProps as MuiLinkProps } from '@mui/material';
import { RouterLink, RouterLinkProps } from '@tanstack/react-router';

// 合并两种组件的属性类型,排除冲突字段
type MuiTanStackLinkProps<TTo> = Omit<MuiLinkProps, 'component' | 'href'> & 
  Omit<RouterLinkProps<TTo>, 'to'> & {
    to: RouterLinkProps<TTo>['to'];
  };

export const MuiTanStackLink = <TTo,>(props: MuiTanStackLinkProps<TTo>) => {
  const { to, ...muiProps } = props;
  return (
    <MuiLink
      component={RouterLink}
      to={to}
      {...muiProps}
    />
  );
};

2. 使用自定义组件跳转路由

替换原MuiLink用法,改用自定义的MuiTanStackLink:

<ListItem>
  <MuiTanStackLink
    to={itemViewRoute.to}
    preload={'intent'}
    search={{}}
    params={{ itemId: '42' }}
  >
    View Item 42 (MuiTanStackLink)
  </MuiTanStackLink>
</ListItem>

3. 全局主题配置(可选)

若希望全局默认使用该集成组件,修改主题配置:

const muiLightTheme = createTheme({
  components: {
    MuiLink: {
      defaultComponent: MuiTanStackLink,
    },
    // 其他组件配置...
  },
});

原理说明

错误根源是MUI Link的默认类型未包含TanStack RouterLink的params等属性类型,导致TypeScript无法识别路由参数。通过自定义组件合并两种组件的类型定义,让TypeScript能够正确推断参数类型,从而通过类型检查。

内容的提问来源于stack exchange,提问作者Shorn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:55:06