JSX element type does not have any construct or call signatures

avatar
Borislav Hadzhiev

Last updated: Jan 15, 2023
4 min

banner

# 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="Bobby" /> </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.

# Type the prop as React.ElementType

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="Bobby" /> </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;

type prop as react element type

Note that React.ElementType can be passed a generic for the type of props 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 a capital letter const {comp: Comp} = props; return ( <div> <Comp name="Bobby" /> </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 auto-completion when passing props to the component.

# Using React.ComponentType to solve the error

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 a capital letter const {comp: Comp} = props; return ( <div> <Comp name="Bobby" /> </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 doesn't default to the any type, so we are required to explicitly type the props.

# Passing a JSX element as props to a component

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="Bobby" />} /> </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 you pass multiple child elements to a component that takes a single JSX.Element, you'd get the error This JSX tag's children prop expects single child of type Element, but multiple children were provided.

# Update your React.js typings

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

update your react js typings

I've written a detailed guide on how to update your React.js typings correctly.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

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.

Copyright ยฉ 2024 Borislav Hadzhiev