Я написал код:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Я получаю сообщение об ошибке:
Тип элемента JSX
Elem
не имеет никаких строковых или сигнальных сигнатур
Что это значит?
Я написал код:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Я получаю сообщение об ошибке:
Тип элемента JSX
Elem
не имеет никаких строковых или сигнальных сигнатур
Что это значит?
Это путаница между конструкторами и экземплярами.
Помните, что когда вы пишете компонент в 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>;
}
Если вы хотите взять класс компонента в качестве параметра (вместо экземпляра), используйте React.ComponentClass
:
function renderGreeting(Elem: React.ComponentClass<any>) {
return <span>Hello, <Elem />!</span>;
}
Когда я конвертирую из 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")
Если вы действительно не заботитесь о реквизите, тогда самый широкий тип - React.ReactType
.
Это позволит передавать нативные элементы dom в виде строки. React.ReactType
охватывает все это:
renderGreeting('button');
renderGreeting(() => 'Hello, World!');
renderGreeting(class Foo extends React.Component {
render() {
return 'Hello, World!'
}
});
Если вы используете 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
каждый раз, когда вы используете компонент.
В моем случае я пропустил 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>
);