将JSX私有路由组件转为TSX遇类型错误,求解决方案
解决React私有路由从JSX转TSX的类型错误问题
首先得帮你理清原JSX代码里的语法,你困惑的({ component: Component, ...rest })是对象解构并重命名的写法:意思是从组件接收的props对象里,取出名为component的属性,把它重命名为Component(大写开头符合组件命名规范),剩下的所有props属性都收集到rest对象里——这和你TSX代码里把Component当第一个参数、rest当剩余参数的写法完全不是一回事,这也是你报错的核心原因之一。
接下来看你遇到的TypeScript错误:JSX element type 'Component' does not have any construct or call signatures,这是因为你给Component的类型注解React.Component不对,这个类型是指类组件的实例类型,而不是组件本身的类型。我们需要用React.ComponentType,它能同时兼容函数组件和类组件,是React组件的通用类型。
下面是和原JSX逻辑完全等价的TSX正确实现:
import React from 'react'; import { Route, Redirect, RouteProps } from 'react-router-dom'; // 定义私有路由的Props类型:继承RouteProps但排除自带的component属性,再加上我们自己的component type PrivateRouteProps = Omit<RouteProps, 'component'> & { component: React.ComponentType<RouteProps>; }; export const PrivateRoute: React.FC<PrivateRouteProps> = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={(props) => localStorage.getItem('user') ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: '/login', state: { from: props.location } }} /> ) } /> ); };
关键细节说明:
React.ComponentType<RouteProps>:这个类型告诉TypeScript,Component是一个可以接收Route渲染时传入的props(比如location、history等)的React组件,不管是函数组件还是类组件都能匹配,直接解决了构造/调用签名的错误。Omit<RouteProps, 'component'>:RouteProps是react-router-dom提供的Route组件的props类型,里面本身就包含component属性,我们用Omit把它排除掉,再重新定义自己的component属性,避免类型冲突。- 解构写法和原JSX保持一致:
({ component: Component, ...rest })确保我们正确提取了要渲染的组件,剩下的props(比如path、exact)都传给底层的Route组件。
如果你更习惯用函数声明而不是箭头函数,也可以这么写:
import React from 'react'; import { Route, Redirect, RouteProps } from 'react-router-dom'; type PrivateRouteProps = Omit<RouteProps, 'component'> & { component: React.ComponentType<RouteProps>; }; export function PrivateRoute({ component: Component, ...rest }: PrivateRouteProps) { return ( <Route {...rest} render={(props) => localStorage.getItem('user') ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: '/login', state: { from: props.location } }} /> ) } /> ); }
内容的提问来源于stack exchange,提问作者Doctor Vermilion Wizard
相关产品推荐
相关产品推荐

