JSX element type does not have any construct or call signatures

avatar

Borislav Hadzhiev

Last updated: Jul 25, 2022

banner

Photo from Unsplash

JSX element type does not have any construct or call signatures #

The error "JSX element type does not have any construct or call signatures" occurs when we try to pass an element or a react component as props to another component but type the prop incorrectly. To solve the error, use the React.ElementType type.

jsx element does not have any construct or call signatures

Here is an example of how the error occurs.

App.tsx
import React from 'react'; interface Props { comp: JSX.Element; } const Wrapper: React.FunctionComponent<Props> = props => { const {comp: Comp} = props; // ⛔️ JSX element type 'Comp' does not have any construct or call signatures.ts(2604) return ( <div> <Comp name="James" /> </div> ); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => <h2>Hello {name}</h2>; return ( <div> <Wrapper comp={heading} /> </div> ); }; export default App;

We tried to pass a React component as a prop to the Wrapper component, but have typed it as JSX.Element.

To solve the error, type the prop as React.ElementType.

App.tsx
import React from 'react'; interface Props { comp: React.ElementType; // 👈️ type it as React.ElementType } const Wrapper: React.FunctionComponent<Props> = props => { // 👇️ component names must start with capital letter const {comp: Comp} = props; return ( <div> <Comp name="James" /> </div> ); }; const App: React.FunctionComponent = () => { // 👇️ takes a name prop const heading = ({name}: {name: string}) => <h2>Hello {name}</h2>; return ( <div> <Wrapper comp={heading} /> </div> ); }; export default App;
Note that React.ElementType can be passed a generic for the type of the props that the element expects.

In this example we would have to pass it an object that has a name property of type string because that's the prop the heading component takes.

App.tsx
import React from 'react'; interface Props { // ✅ explicitly type props comp takes comp: React.ElementType<{name: string}>; } const Wrapper: React.FunctionComponent<Props> = props => { // 👇️ component names must start with capital letter const {comp: Comp} = props; return ( <div> <Comp name="James" /> </div> ); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => <h2>Hello {name}</h2>; return ( <div> <Wrapper comp={heading} /> </div> ); }; export default App;

Now we explicitly typed the props the comp element takes when used. This helps us leverage our IDE for autocompletion when passing props to the component.

We could also use the React.ComponentType, but then we are required to type the props.

App.tsx
import React from 'react'; interface Props { // 👇️ now using React.ComponentType 👇️ comp: React.ComponentType<{name: string}>; } const Wrapper: React.FunctionComponent<Props> = props => { // 👇️ component names must start with capital letter const {comp: Comp} = props; return ( <div> <Comp name="James" /> </div> ); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => <h2>Hello {name}</h2>; return ( <div> <Wrapper comp={heading} /> </div> ); }; export default App;

The generic in React.ComponentType does not default to the any type, so we are required to explicitly type the props.

If you need to pass a JSX element as props to a component, and not an actual component, then JSX.Element is the correct type.

App.tsx
import React from 'react'; interface Props { // 👇️ using JSX.Element type comp: JSX.Element; } const Wrapper: React.FunctionComponent<Props> = props => { const {comp: Comp} = props; // 👇️ use as {Comp} return <div>{Comp}</div>; }; const App: React.FunctionComponent = () => { const Heading = ({name}: {name: string}) => <h2>Hello {name}</h2>; // 👇️ we are passing an actual JSX element // because we didn't pass it as comp={Heading} return ( <div> <Wrapper comp={<Heading name="James" />} /> </div> ); }; export default App;

We typed the comp prop as JSX.Element because we are passing an actual JSX element (not a component) to the Wrapper component.

We are passing a JSX element because we passed the prop as comp={<Heading />} instead of comp={(props) => <h2>Hello world</h2>}.

Notice that in the first case we are passing a JSX element prop, whereas in the second, we are passing a function that returns a JSX element (a functional component).

We shouldn't try to use the JSX element as a component in our Wrapper component, e.g. don't do <Comp />, instead do {Comp}.

We haven't passed an actual component as a prop, we passed a JSX element, so it shouldn't be used as a component.

If none of the previous suggestions helped, try to update the versions of your React typings by running the following commands.

shell
# 👇️ with NPM npm install react@latest react-dom@latest npm install --save-dev @types/react@latest @types/react-dom@latest # ---------------------------------------------- # 👇️ with YARN yarn add react@latest react-dom@latest yarn add @types/react@latest @types/react-dom@latest --dev

Conclusion #

The error "JSX element type does not have any construct or call signatures" occurs when we try to pass an element or a react component as props to another component but type the prop incorrectly. To solve the error, use the React.ElementType type.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.