Подтвердить что ты не робот

Что означает ошибка "Тип элемента JSX"..."не содержит каких-либо конструкций или сигнатур?

Я написал код:

function renderGreeting(Elem: React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

Я получаю сообщение об ошибке:

Тип элемента JSX Elem не имеет никаких строковых или сигнальных сигнатур

Что это значит?

4b9b3361

Ответ 1

Это путаница между конструкторами и экземплярами.

Помните, что когда вы пишете компонент в React:

class Greeter extends React.Component<any, any> {
    render() {
        return <div>Hello, {this.props.whoToGreet}</div>;
    }
}

Вы используете его следующим образом:

return <Greeter whoToGreet='world' />;

Вы не используете его так:

let Greet = new Greeter();
return <Greet whoToGreet='world' />;

В первом примере мы обходим Greeter, конструкторную функцию для нашего компонента. Это правильное использование. Во втором примере мы просматриваем экземпляр Greeter. Это неверно и будет работать во время выполнения с ошибкой типа "Объект не является функцией".


Проблема с этим кодом

function renderGreeting(Elem: React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

заключается в том, что он ожидает экземпляр React.Component. Что вы хотите использовать функцию, которая принимает конструктор для React.Component:

function renderGreeting(Elem: new() => React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

или аналогичным образом:

function renderGreeting(Elem: typeof React.Component) {
    return <span>Hello, <Elem />!</span>;
}

Ответ 2

Если вы хотите взять класс компонента в качестве параметра (вместо экземпляра), используйте React.ComponentClass:

function renderGreeting(Elem: React.ComponentClass<any>) {
    return <span>Hello, <Elem />!</span>;
}

Ответ 3

Когда я конвертирую из JSX в TSX и мы сохраняем некоторые библиотеки как js/jsx и конвертируем другие в ts/tsx, я почти всегда забываю изменить операторы импорта js/jsx в файлах TSX\TS из

import * as ComponentName from "ComponentName";

в

import ComponentName from "ComponentName";

Если вызывается старый компонент стиля JSX (React.createClass) из TSX, используйте

var ComponentName = require("ComponentName")

Ответ 4

Если вы действительно не заботитесь о реквизите, тогда самый широкий тип - React.ReactType.

Это позволит передавать нативные элементы dom в виде строки. React.ReactType охватывает все это:

renderGreeting('button');
renderGreeting(() => 'Hello, World!');
renderGreeting(class Foo extends React.Component {
   render() {
      return 'Hello, World!'
   }
});

Ответ 5

Если вы используете Material-UI, перейдите к определению типа компонента, который подчеркивается TypeScript. Скорее всего, вы увидите что-то подобное

export { default } from './ComponentName';

У вас есть 2 варианта для устранения ошибки:

1. Добавьте .default при использовании компонента в JSX:

import ComponentName from './ComponentName'

const Component = () => <ComponentName.default />

2. Переименуйте компонент, который экспортируется как "по умолчанию", при импорте:

import { default as ComponentName } from './ComponentName'

const Component = () => <ComponentName />

Таким образом, вам не нужно указывать .default каждый раз, когда вы используете компонент.

Ответ 6

В моем случае я пропустил new внутри определения типа.

Файл some-js-component.d.ts:

import * as React from "react";

export default class SomeJSXComponent extends React.Component<any, any> {
    new (props: any, context?: any)
}

и внутри файла tsx, где я пытался импортировать нетипизированный компонент:

import SomeJSXComponent from 'some-js-component'

...inside render()
   return (
        <React.Fragment>
            <SomeJSXComponent withProps={asdf} />
        </React.Fragment>
   );