Question
Understanding "JSX element type does not have any construct or call signatures" in React and TypeScript
Question
In React with TypeScript, I wrote the following code:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
TypeScript shows this error:
JSX element type 'Elem' does not have any construct or call signatures.
What does this error mean, and how should a component parameter be typed so it can be used as <Elem /> inside JSX?
Short Answer
By the end of this page, you will understand why TypeScript rejects some values in JSX, what "construct or call signatures" means, and how to correctly type a React component passed as a variable. You will also see the difference between a component instance, a component type, and a rendered React element.
Concept
In React, writing <Elem /> means "render the component stored in Elem". For TypeScript to allow that, Elem must be a component type that can be called like a function component or constructed like a class component.
The error:
JSX element type 'Elem' does not have any construct or call signatures.
means TypeScript looked at the type of Elem and concluded:
- it is not callable like a function, and
- it is not constructable like a class
So TypeScript cannot safely treat it as a JSX component.
In your example, React.Component<any, any> is the wrong type for Elem.
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
describes a object, not a component definition. JSX needs the definition/type of a component, not an already-created instance.
Mental Model
Think of three different things:
- Blueprint: the component definition itself, like
MyButton - Built object: an instance created from that blueprint
- Final output: the rendered element, like what JSX produces
When you write:
<MyButton />
React needs the blueprint, not the built object.
Your original type used React.Component, which is closer to the built object/instance idea. But JSX expects something it can use to create an element: a function component or class component type.
So the error is TypeScript saying:
"You gave me something that does not look like a component blueprint I can call or construct."
Syntax and Examples
The most common fix is to type the parameter as React.ComponentType.
Component with no props
function renderGreeting(Elem: React.ComponentType) {
return (
<span>
Hello, <Elem />!
</span>
);
}
Example usage:
const Name = () => <>Alice</>;
renderGreeting(Name);
Name is a function component, so TypeScript allows <Elem />.
Component with props
If the component needs props, include them in the type:
type UserProps = {
name: string;
};
function () {
(
);
}
Step by Step Execution
Consider this example:
type Props = { name: string };
const UserName = ({ name }: Props) => <strong>{name}</strong>;
function renderGreeting(Elem: React.ComponentType<Props>) {
return (
<div>
Hello, <Elem name="Sam" />
</div>
);
}
const result = renderGreeting(UserName);
Step by step
-
Propsis defined as:{ name: string } -
UserNameis a function component that accepts those props.
Real World Use Cases
Passing components as values is common in React applications.
Reusable layout components
A layout may receive a component to render inside a slot:
type SlotProps = { title: string };
function PageHeader(Header: React.ComponentType<SlotProps>) {
return <Header title="Dashboard" />;
}
Route configuration
Many apps store component references in route definitions:
type Route = {
path: string;
component: React.ComponentType;
};
Render props and pluggable UI
Design systems and dashboards often allow users to supply custom components:
- custom icon components
- custom row renderers
- custom form field renderers
Generic wrappers
A utility may accept a component and inject shared props:
Real Codebase Usage
In real projects, developers usually use a few common patterns.
Accepting a component prop
type EmptyStateProps = {
Illustration: React.ComponentType;
};
function EmptyState({ Illustration }: EmptyStateProps) {
return (
<div>
<Illustration />
<p>No data found.</p>
</div>
);
}
Guarding props with explicit component types
When a component requires props, developers encode that into the type:
type BadgeProps = { label: string };
type CardProps = {
Badge: React.ComponentType<BadgeProps>;
};
This avoids runtime mistakes because TypeScript enforces the required props.
Using ElementType for "as" props
Common Mistakes
1. Using React.Component instead of React.ComponentType
Broken code:
function renderGreeting(Elem: React.Component<any, any>) {
return <Elem />;
}
Why it fails:
React.Componentis an instance type- JSX needs a component type
Fix:
function renderGreeting(Elem: React.ComponentType) {
return <Elem />;
}
2. Passing a rendered element instead of a component
Broken code:
const Name = () => <>Alice;
();
Comparisons
| Type | What it represents | Can be used as <Elem />? | Typical use |
|---|---|---|---|
React.Component<P, S> | A class component instance | No | Rarely used directly for JSX variables |
React.ComponentType<P> | Any React component type (function or class) | Yes | Best choice when accepting a component |
React.ElementType | Any valid JSX element type, including 'div' | Yes | Useful for as props or dynamic tags |
JSX.Element | A rendered React element | No | Return type of JSX expressions |
Cheat Sheet
// Accept any React component with no props
function fn(Elem: React.ComponentType) {
return <Elem />;
}
// Accept a React component with props
function fn(Elem: React.ComponentType<{ name: string }>) {
return <Elem name="Alice" />;
}
// Accept a component OR intrinsic tag like 'div'
function fn(Elem: React.ElementType) {
return <Elem />;
}
Quick rules
<Elem />requiresElemto be a valid JSX element typeReact.Componentis not the right type for this caseReact.ComponentType<Props>is the usual fix
FAQ
What does "construct or call signatures" mean in TypeScript?
It means TypeScript expects a value that can be used like a function or class. JSX components must be callable as function components or constructable as class components.
Why does React.Component cause this error?
Because React.Component describes a component instance, not the component type that JSX needs to create an element.
Should I use React.ComponentType or React.ElementType?
Use React.ComponentType when you want a React component only. Use React.ElementType when you also want to allow strings like 'div' or 'button'.
What is the difference between MyComp and <MyComp />?
MyComp is the component itself. <MyComp /> is the rendered element created from it.
Can class components also use React.ComponentType?
Yes. React.ComponentType covers both function components and class components.
Mini Project
Description
Build a small greeting utility that accepts different React components and renders them inside a greeting message. This project demonstrates the difference between component types, rendered elements, and prop-aware typing in TypeScript.
Goal
Create a reusable function and component setup that safely accepts React components as arguments and renders them with the correct props.
Requirements
[ "Create one component that takes no props and one component that takes a name prop.", "Write one function that accepts a no-props component using the correct type.", "Write another function that accepts a component with typed props and renders it correctly.", "Demonstrate valid usage by passing component references, not rendered elements.", "Include one example using React.ElementType with an intrinsic tag like 'section'." ]
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular @ViewChild Returning Undefined: Lifecycle, Child Components, and Fixes
Learn why Angular @ViewChild can be undefined, when it becomes available, and how to access child components correctly using lifecycle hooks.