React Router v6 withRouter包装器TypeScript类型定义及报错解决
为React Router的withRouter包装器添加正确TypeScript类型
问题背景
为避免将所有类组件重构为函数组件,采用React Router文档提供的withRouter包装器,但需要为包装器中的Component和props添加正确TypeScript类型(不想使用any)。尝试使用React.ComponentType后,TypeScript在传递router属性时抛出报错:
Type '{ router: { location: Location; navigate: NavigateFunction; params: Readonly<Params<string>>; }; }' is not assignable to type 'IntrinsicAttributes'. Property 'router' does not exist on type 'IntrinsicAttributes'.
解决方案
通过泛型结合类型合并的方式,让withRouter能准确识别目标组件的props类型,同时明确注入的router属性类型,具体实现如下:
1. 定义Router属性类型
先从react-router-dom导入相关类型,再定义注入的router属性结构:
import { useLocation, useNavigate, useParams, Location, NavigateFunction, Params } from "react-router-dom"; import type React from "react"; // 明确注入的router属性类型 type RouterProps = { router: { location: Location; navigate: NavigateFunction; params: Readonly<Params<string>>; }; };
2. 实现带类型的withRouter
通过泛型P捕获目标组件的props类型,将RouterProps与P合并,确保组件能正确接收自动注入的router属性:
function withRouter<P extends object>(Component: React.ComponentType<P & RouterProps>) { function ComponentWithRouterProp(props: Omit<P, keyof RouterProps>) { const location = useLocation(); const navigate = useNavigate(); const params = useParams(); return ( <Component {...props as P} router={{ location, navigate, params }} /> ); } return ComponentWithRouterProp; } export default withRouter;
3. 使用示例
用该包装器包裹类组件时,组件props可直接声明router属性,TypeScript会自动完成类型校验:
import React from "react"; import withRouter from "./withRouter"; import type { RouterProps } from "./withRouter"; class MyClassComponent extends React.Component<{ // 组件自身的业务props pageTitle: string; // 注入的router属性 router: RouterProps['router']; }> { render() { return ( <div> <h2>{this.props.pageTitle}</h2> <p>当前路径:{this.props.router.location.pathname}</p> </div> ); } } // 包装后导出组件,无需手动传入router属性 export default withRouter(MyClassComponent);
关键说明
- 泛型
P用于捕获目标组件的自身props类型,P & RouterProps表示组件需要同时接收自身props和注入的router属性 Omit<P, keyof RouterProps>确保包装后的组件不需要手动传入router属性,由withRouter自动注入- 完全避免了
any类型,同时保证TypeScript能正确校验所有props的合法性
内容的提问来源于stack exchange,提问作者user18943198
相关产品推荐
相关产品推荐

