Last updated: Feb 29, 2024
Reading timeยท4 min
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.
Here is an example of how the error occurs.
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
.
React.ElementType
To solve the error, type the prop as React.ElementType
.
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 a 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;
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.
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.
React.ComponentType
to solve the errorWe could also use the React.ComponentType
, but then we are required to type
the props.
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.
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.
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>}
.
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.
If none of the previous suggestions helped, try to update the versions of your React typings by running the following commands.
# ๐๏ธ 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
I've written a detailed guide on how to update your React.js typings correctly.
You can learn more about the related topics by checking out the following tutorials: