TypeScript+React:如何根据href动态指定Link组件params的类型
当然可以!我们可以通过TypeScript的泛型和索引类型实现这个动态匹配的类型化API,让params的类型严格跟随你传入的href值。下面是具体的实现方案:
1. 重构
LinkProps为泛型类型 把原来固定的LinkProps改成接受泛型参数的类型,让params的类型直接关联到href对应的路由参数定义:
import type { AnchorHTMLAttributes } from 'react'; type LinkProps<R extends Routes> = { href: R; // 自动匹配对应路由的参数类型:不需要参数时可选,需要时必填 params?: RouteParams[R]; } & AnchorHTMLAttributes<HTMLAnchorElement>; // 继承a标签的原生属性
2. 实现泛型
Link组件 用泛型函数定义组件,TypeScript会根据你传入的href自动推断出对应的泛型类型,进而约束params的结构:
const Link = <R extends Routes>(props: LinkProps<R>) => { // 实现路由参数拼接逻辑(示例) const resolveHref = (): string => { if (!props.params) return props.href; return Object.entries(props.params).reduce((resolved, [key, value]) => { return resolved.replace(`[${key}]`, value); }, props.href); }; return <a href={resolveHref()} {...props} />; };
3. 验证类型校验效果
现在使用组件时,TypeScript会自动进行精准的类型检查:
- ✅
<Link href={Routes.CONTACT} />类型校验通过(该路由无需参数) - ❌
<Link href={Routes.PRODUCT} />报错:提示缺少必填的params属性 - ❌
<Link href={Routes.PRODUCT} params={{}} />报错:提示缺少productId字段 - ✅
<Link href={Routes.PRODUCT} params={{ productId: '123' }} />类型校验通过
进阶:严格禁止不必要的参数
如果你希望当路由不需要参数时,完全不能传入params(而不仅仅是可选),可以用条件类型进一步约束:
type LinkProps<R extends Routes> = { href: R; } & (RouteParams[R] extends undefined ? { params?: never } // 无需参数时,params不能传任何值 : { params: RouteParams[R] }); // 需要参数时,params必填
这样<Link href={Routes.CONTACT} params={{}} />也会触发类型错误,更符合预期。
内容的提问来源于stack exchange,提问作者sherlock
相关产品推荐
相关产品推荐

