Generic usage reported as JSX Error #15713
Copy link
Copy link
Closed
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
Description
TypeScript Version: 2.2.2 & 2.3.2
Code
// Basic example
const paramArray = <T>(param1: T, param2: T) => [param1, param2];
// React specific example
type Component<T> = React.ComponentClass<T> | React.StatelessComponent<T>;
const decorator = <T>(Component: Component<T>) : Component<T> => (props) => <Component {...props} />Expected behavior:
Both examples should work in a .tsx file in addition to the basic example working in a .ts file.
Actual behavior:
The usage of <T> prior to the function braces causes a JSX error within .tsx files: "JSX element has no corresponding closing tag.". Basic example works as expected in a .ts file.
Specifying an unused type variable seems to be a workaround to avoid the error:
const paramArray = <T1, T2>(param1: T1, param2: T1) => [param1, param2];Reacted by Ricardo Fernández Serrata
Reacted by Elhay Avihezer, Volodymyr Kovalchuk, KENOBI IO, Téo Orthlieb, Saad A. Bazaz, Ivan Ilinykh, stephen304, sandeshsapkota, Jernej Oblak, Kavin Raju Sridhar and 3 more
Metadata
Metadata
Assignees
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
Activity
mhegazy commentedon May 10, 2017
This is a limitation cased by the use of
<T>for generic type parameter declarations. combined with JSX grammar, it makes such components ambiguous to parse.The workaround is to use a function expression instead:
niieani commentedon Dec 22, 2017
Mohamed Hegazy (@mhegazy) I can't agree that this a design limitation or that it is ambiguous. It might be harder to parse, but it's definitely possible. Both Babylon and Flow parsers do this correctly. The reason is declaration of a JSX component like
<T>must be followed by either a string literal or a token such as{, and end with the corresponding JSX closing tag</T>.Babel's transpilation of these two cases:
=>
Could you consider re-opening this as a bug?
reverie commentedon Jun 6, 2019
In case this helps anyone arriving here, you can use a trailing comma after the type name to get around the ambiguity. For example:
const f = <T,>(arg: T): T => {...}. Thanks to Thomas in this StackOverflow comment for the pointer.danielo515 commentedon Jan 15, 2022
So this is going to be a permanent issue for the foreseeable future?
spencergray96 commentedon Oct 7, 2022
This works if you need to make a generic component that is also connected to Redux, only "caveat" is having to define the component multiple times, once for each type you are going to use:
bingDBdu commentedon Apr 18, 2024
So there is a bug. we found it. We avoided it but we won't intend to fix it.
Everybody meets it and tries to find the solution here. Holy TS
shiv-raj45 commentedon Jul 10, 2024
extending empty object with generic worked for me
const AppTable = <T extends {}>({ columns, data }: IProps<T>) => { return <DataTable columns={columns} data={data} />; };Rudxain commentedon Aug 11, 2025
This issue seems to have been fixed (at least, for non-component fns in non-JSX files), but I can't find the commit or PR that patches it