What does the error "JSX element type '...' does not have any construct or call signatures" mean?
I wrote some code:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
I'm getting an error:
JSX element type
Elem
does not have any construct or call signatures
What does it mean?
This is a confusion between constructors and instances.
Remember that when you write a component in React:
class Greeter extends React.Component<any, any> {
render() {
return <div>Hello, {this.props.whoToGreet}</div>;
}
}
You use it this way:
return <Greeter whoToGreet='world' />;
You don't use it this way:
let Greet = new Greeter();
return <Greet whoToGreet='world' />;
In the first example, we're passing around Greeter
, the constructor function for our component. That's the correct usage. In the second example, we're passing around an instance of Greeter
. That's incorrect, and will fail at runtime with an error like "Object is not a function".
The problem with this code
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
is that it's expecting an instance of React.Component
. What you want is a function that takes a constructor for React.Component
:
function renderGreeting(Elem: new() => React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
or similarly:
function renderGreeting(Elem: typeof React.Component) {
return <span>Hello, <Elem />!</span>;
}
If you want to take a component class as a parameter (vs an instance), use React.ComponentClass
:
function renderGreeting(Elem: React.ComponentClass<any>) {
return <span>Hello, <Elem />!</span>;
}
When I'm converting from JSX to TSX and we keep some libraries as js/jsx and convert others to ts/tsx I almost always forget to change the js/jsx import statements in the TSX\TS files from
import * as ComponentName from "ComponentName";
to
import ComponentName from "ComponentName";
If calling an old JSX (React.createClass) style component from TSX, then use
var ComponentName = require("ComponentName")