打字稿类型定义:TS2604:JSX元素类型“某物”没有任何构造或调用签名

时间:2018-11-23 15:13:00

标签: javascript reactjs typescript types

我在“ File1”中有一个抽象类:

// File1.tsx

import * as React from 'react';

export interface IProps {
  prop1: string;
  prop2: number;
}

export abstract class Something extends React.Component<IProps> {
  public typeName: string;
}

然后,在其他文件(File2)中,我定义了从抽象类Something扩展的无限类:

// File2.tsx

import { Something } from './File1';

export class Something1 extends Something {
  public typeName: string = 'Type1';

  public render() {
    return <div>Something 1</div>
  }
}

export class Something2 extends Something {
  public typeName: string = 'Type2';

  public render() {
    return <div>Something 2</div>
  }
}

现在,这是我的问题: 在第三个文件中,我导入之前定义的类(Something1或Something2),然后将该类传递给2个不同的组件:ReadProperty和RenderComponent。在第一个组件中,我需要访问该类的属性typeName并进行一些操作,在第二个文件中,我需要渲染该类:

// File3.tsx

import { Something } from './File1';
import { Something1, Something2 } from './File2';

interface IReadProperty {
  something: Something;
};

const ReadProperty: React.SFC<IReadProperty> = ({ something }) => {
  // here i can access to property typeName. No problem here.

  something.typeName // Type1 | Type2 | ... Infinite

  ...do some stuff
}


interface IRenderComponent {
  something: Something;
}

const RenderComponent: React.SFC<IRenderComponent> = ({ something }) => {
  // i need do some stuff here before render "something" component
  // here i get an error when i try render the component
  return <something />;
}


const Main: React.SFC = () => {
  return (
    <div>
      <ReadProperty something={Something1} />
      <RenderComponent something={Something1} />
    </div>
  );
}

但是当我尝试在RenderComponent中渲染组件时,出现以下错误:TS2604:JSX元素类型'something'没有任何构造或调用签名。

这是怎么了?我将类型'something'定义为抽象类Something,因为我可以定义从Something扩展的无限类,因此我无法使用以下方法进行定义:something:Something1 |东西2 | Something50 ...;

这是我尝试做的一个示例:https://codesandbox.io/s/18yzvkx8jj

2 个答案:

答案 0 :(得分:0)

  1. 确保您在jsx:react中有tsconfig.json
  2. 请确保您拥有react react-dom @types/react@types/react-dom软件包版本的一致版本。

答案 1 :(得分:0)

问题在于,在您对IRenderComponent的定义中,您说somethingSomething实例,而您想要的是构造函数类型。另一件事是,当您尝试使用小写名称实例化组件时,React通常会抱怨。试试这个:

interface IRenderComponent {
  Something: new (props: IProps) => Something1;
};

const RenderComponent: React.SFC<IRenderComponent> = ({ Something }) => {
  return <Something prop1="foo" prop2={3} />;
}

对于IReadProperty,看来您 do 想要Something的实例(因为您要访问typeName,这是一个实例属性)。但是,您实际上无法传递实例化的组件:

<ReadProperty something={<Something1 prop1="" prop2={3} />;} /> //Error

这是因为<Something1 ... />实际上不是Something1的实例-它是JSX.Element的实例。您可以像这样传递Something1的实例:

<ReadProperty something={new Something1({prop1: "", prop2: 3})} />

但是我想那不是您想要的,因为您实际上不能在渲染中使用生成的实例。

解决IReadProperty问题的最佳方法取决于您实际要完成的工作。一般来说,React倾向于使用组合而不是继承和反射,因此从基础组件开始并进行组合或使用高阶组件可能更容易考虑如何实现目标。