TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]

Posted

技术标签:

【中文标题】TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]【英文标题】:TypeScript 3: JSX element type 'Component' does not have any construct or call signatures. [2604] 【发布时间】:2019-04-26 10:28:54 【问题描述】:

我正在尝试将 React.Component(或 React.FunctionComponent)类型的变量传递给 Route,如下所示:

import React from 'react';
import  Route  from 'react-router-dom';

type PrivateRouteProps = 
  component: React.Component | React.FunctionComponent;
  isAuthenticated: boolean;
  login: (...args: any[]) => any;
  path: string;
;

const PrivateRoute: React.FunctionComponent<PrivateRouteProps> = (
  component: Component,
  isAuthenticated,
  login,
  path,
  ...rest
) => 
  return (
    <Route
      path=path
      ...rest
      render=props => 
        if (isAuthenticated) 
          return <Component ...props />;
         else 
          login();
          return null;
        
      
    />
  );
;

但我收到此错误:

JSX 元素类型“组件”没有任何构造或调用签名。 [2604]

我已经阅读了很多关于这个问题的其他线程,但它们似乎都处理了针对特定组件实现出现的这个错误。我无法更改有问题的组件或以不同方式导入它(就像公认的答案通常建议的那样),因为它可能是 any 组件。

我正在使用 TypeScript 3.1.6、Babel Core 7.1 和 React 16.6.3。

【问题讨论】:

【参考方案1】:

派对迟到了,"@types/react-router-dom": "^4.3.4""@types/react": "16.9.1",如果你使用的是 RouteProps,你可能会得到同样的错误。

JSX 元素类型“组件”没有任何构造或调用签名。 [2604]

这是因为,在RouteProps 接口中,component 被定义为可选,因此它可能是未定义的。

export interface RouteProps 
  location?: H.Location;
  component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
  render?: ((props: RouteComponentProps<any>) => React.ReactNode);
  children?: ((props: RouteChildrenProps<any>) => React.ReactNode) | React.ReactNode;
  path?: string | string[];
  exact?: boolean;
  sensitive?: boolean;
  strict?: boolean;

只需检查component 是否虚假即可修复它。

function PrivateRoute( component: Component, ...rest : RouteProps) 
  if (!Component) return null;
  return (
    <Route
      ...rest
      render=props =>
        fakeAuth.isAuthenticated ? (
          <Component ...props />
        ) : (
          <Redirect
            to=
              pathname: "/login",
              state:  from: props.location 
            
          />
        )
      
    />
  );

【讨论】:

我一般不会写无用的“谢谢”cmets,但谢谢!我一直在深入挖掘,这是唯一提到条件性作为潜在问题的事情,它为我解决了这个问题。 谢谢,这真的很有用!我没有意识到这一点:) 这应该是公认的答案。无需将类型设置为React.ElementType【参考方案2】:

我遇到过几次。试试这些:

    将您的PrivateRoute 输入为React.FC&lt;Props&gt; 将传入的组件键入为React.ElementType

关于 React 类型的终极真相来自the docs

编辑:React.ReactType(已弃用)-> React.ElementType

【讨论】:

#2 为我工作。现在是时候进行一些研究并弄清楚它为什么起作用了。也感谢您提供文档链接。 export const BackNavigationTextWrapper = (WrappedComponent: typeof React.Component) =&gt; const BackNavigationTextWrappedComponent = (props, commonElements = : any) =&gt; return &lt;WrappedComponent ...props backLabel=commonElements.backLabel || 'Go back to reservation details' /&gt; ; BackNavigationTextWrappedComponent.type = WrappedComponent.type; return BackNavigationTextWrappedComponent; ; 我收到错误消息“类型'typeof Component'上不存在属性'type'”。 尝试了 React.ReactType 并且它可以工作,但它似乎已被弃用,因此当前合适的类型是 React.ElementType。 VS Code 中没有错误。【参考方案3】:

晚会,但对我有用的是:

interface PrivateRouteProps extends Omit<RouteProps, "component"> 
  component: React.ElementType;
  // any additional vars


PrivateRoute: React.FC<PrivateRouteProps> = (
  component: Component,
  ...rest
) => 
// render code

【讨论】:

IMO,这是最好的答案,因为这样可以防止在没有组件的情况下使用 PrivateRoute。【参考方案4】:

【讨论】:

非常适合我 这对我来说非常有用,但我通过使组件可选来对其进行了一些修改。 type PrivateRouteProps = component?: React.ElementType &amp; RouteProps【参考方案5】:

这已经晚了,但如果有人不想要一个解决方案而是一个解释,让我们用一个例子来讨论这个错误来演示它

function PaymentPage()
  
   return <div>Payment Page</div>


假设我们想创建一个动态支付表单,如果查询参数是 with=stripe,那么我们假设他想用 stripe 支付,如果是 razorpay 我们假设它,...等等。

然后我们做类似的事情

function PaymentPage()
   const router = useRouter;
   const with_ = router.query;
   let GatewayComponent: Gateway | null = null;
   switch(with_)
     case 'stripe':
       GatewayComponent = <StripeGateway/>;
       break;
     case 'razorpay':
       GatewayComponent = <RazorpayGateway/>;
       break;
   
   return <GatewayComponent/>

运行这个,我们得到

JSX element type 'Component' does not have any construct or call signatures.

会发生什么?

什么是组件?

返回 JSX.Element 类型元素的构造函数

那么?

我们不是返回一个构造函数,我们是返回一个构造函数调用,这和假设GatewayComponent是一个构造函数一样,但它不是,它是一个持有 JSX 的变量

所以基本上,期望 x 是任何类型的构造函数,无论是函数还是类,如果是函数,则函数是渲染函数,如果是类,则需要渲染方法。

回到我们的问题

function PaymentPage()
   const router = useRouter;
   const with_ = router.query;
   let gateway: Gateway | null = null;
   switch(with_)
     case 'stripe':
       gateway = <StripeGateway/>;
       break;
     case 'razorpay':
       gateway = <RazorpayGateway/>
       break;
   
   return <React.Fragment> gateway </React.Fragment>

因为 gateway 持有 JSX,而不是返回 JSX 的构造函数

如果你想把它作为一个组件使用呢?

function PaymentPage()
   const router = useRouter;
   const with = router.query;
   let GatewayComponent: Gateway | null = null;
   switch(with_)
     case 'stripe':
       return () => <StripeGateway/>
     case 'razorpay':
       return () => <RazorpayGateway/>
   
   return <GatewayComponent/>

现在它是一个构造函数,我们现在可以将它用作一个组件。

正式地,你传递的是构造函数而不是实例。

【讨论】:

我根本没有遵循这个。您的示例与原始问题不同,因此我不知道如何关联。哪一行返回错误?【参考方案6】:

我可以通过如下输入我的组件来解决错误:

...
export function withApollo (PageComponent: () => JSX.Element) 
const WithApollo = <T extends object>(props: T) => 
...

【讨论】:

以上是关于TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]的主要内容,如果未能解决你的问题,请参考以下文章

LayaBox---TypeScript---JSX

TypeScript、react-router 和 jsx:JSX 元素类型 'Route' 没有任何构造或调用签名

打字稿:未找到导出/JSX 元素类型没有任何构造或调用签名

带有 react-dnd 的 TypeScript 2.0 给出错误“JSX 元素属性可能不是联合类型”

在Vue 3中使用Typescript和Jsx

如何在 TypeScript 中键入这个“as”JSX 属性?