如何封装Tanstack Router的Link组件并保留类型安全性
问题
我希望将TanStack Router的Link组件封装到自定义组件中,同时能向该组件传递Link所需的props。具体来说,我想制作一个可复用组件,用TanStack Router的Link包裹外部按钮组件,示例代码如下:
import { Link, LinkOptions } from '@tanstack/router' interface ButtonLinkProps { // 如何实现类型安全?当前它的类型为`string | undefined`,而非我定义的有效路由 to: LinkOptions['to'] children: string } export function ButtonLink(props: ButtonLinkProps) { return ( <Link to={props.to} params={{}} search={{}}> <Button component='span'>{props.children}</Button> </Link> ) }
直接使用Link组件时,to prop仅能传入已定义的路由,但我不清楚如何在自定义组件中定义to prop以实现相同的类型安全效果,例如使用<ButtonLink to='/'>Link</ButtonLink>时的类型检查。
解决方案
要实现和原生Link组件一致的类型安全,核心是利用TanStack Router代码生成工具生成的路由类型定义,以下是两种可行方案:
方案1:继承LinkProps类型(推荐)
TanStack Router会在路由生成文件(通常是router.ts)中导出LinkProps类型,该类型已经绑定了你所有已定义的路由信息,直接继承它就能自动获得类型安全的to、params、search等props:
import { Link, LinkProps } from '@tanstack/router'; import { Router } from './router'; // 导入生成的Router类型 import Button from './your-button-component'; // 导入你的外部按钮组件 // 继承LinkProps并扩展自定义属性,Omit去掉默认children后自定义类型(可选) interface ButtonLinkProps extends Omit<LinkProps<Router>, 'children'> { children: string; // 可添加Button组件的自定义props,比如variant、size等 } export function ButtonLink(props: ButtonLinkProps) { const { children, ...linkProps } = props; return ( <Link {...linkProps}> <Button component='span'>{children}</Button> </Link> ); }
方案2:显式约束路由名称类型
如果你只需要部分Link的props,可以直接用生成的Router['routeNames']来约束to的取值范围,确保只能传入已定义的路由:
import { Link } from '@tanstack/router'; import { Router } from './router'; // 导入生成的Router类型 import Button from './your-button-component'; interface ButtonLinkProps { to: Router['routeNames']; // 仅允许传入已定义的路由名称 children: string; // 按需添加其他Link的props,类型自动匹配对应路由的参数 params?: Parameters<typeof Link>[0]['params']; search?: Parameters<typeof Link>[0]['search']; } export function ButtonLink(props: ButtonLinkProps) { const { children, ...linkProps } = props; return ( <Link {...linkProps}> <Button component='span'>{children}</Button> </Link> ); }
关键说明
- 必须确保你已经通过TanStack Router的代码生成工具(比如
@tanstack/router-cli)生成了路由类型文件,否则无法获取Router和LinkProps类型 - 两种方案都能实现:当传入未定义的路由时,TypeScript会直接抛出类型错误,和原生Link组件的类型检查效果完全一致
内容的提问来源于stack exchange,提问作者Sjiep
相关产品推荐
相关产品推荐

