New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Consult new JSX.ElementType for valid JSX element types #51328
base: main
Are you sure you want to change the base?
Conversation
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
The TypeScript team hasn't accepted the linked issue #21699. If you can get it accepted, this PR will have a better chance of being reviewed. |
2 similar comments
The TypeScript team hasn't accepted the linked issue #21699. If you can get it accepted, this PR will have a better chance of being reviewed. |
The TypeScript team hasn't accepted the linked issue #21699. If you can get it accepted, this PR will have a better chance of being reviewed. |
Is this entirely true? This allows TypeScript to customize what sorts of things can be used as tag names, but it doesn't allow users to capture the type returned by these functions as part of a JSX invocation. To be clear, I don't have any specific objections to that direction, especially given that there's several backwards-compatibility issues and a huge performance impact involved in doing something of that sort; but I just think we need to be clear about what is/isn't getting fixed. Maybe that's pedantic. |
I looked at the problems the issues are describing instead of the specific implementation they're proposing (especially #14729). I have no problem in unlinking these issues (though we can always reopen the issues if people think this PR doesn't fully address their issue). I was more concerned this PR is missed/auto-closed because it didn't have an associated issue. |
!!! related TS2728 tests/cases/compiler/jsxElementType.tsx:48:43: 'title' is declared here. | ||
~~~~~~~~~~~~~ | ||
!!! error TS2786: 'RenderPromise' cannot be used as a JSX component. | ||
!!! error TS2786: Its instance type '({ title }: { title: string; }) => Promise<string>' is not a valid JSX element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!!! error TS2786: Its instance type '({ title }: { title: string; }) => Promise<string>' is not a valid JSX element. | |
!!! error TS2786: Its type '({ title }: { title: string; }) => Promise<string>' is not a valid JSX element type. |
sounds more accurate to me.
From today's design meeting (#51344) we had the following questions:
We also had a suggestion:
|
The backstory for the naming was that we already have Which is also why I copied over the type parameter. My original plan was that the type-checker uses the parameter to infer the props type but that's not implemented and I don't know if we'll ever need it. Especially considering the type parameter is ignored for host components (the
That's a bit tricky because in JSX generally and React specifically "element type" is a pretty well defined term. It's comes naturally from We already have
To do what? Are you planning to lookup the React namespace in the TypeScript compiler? In #21699 specifically it was brought up that any solution should also be concerend with other libraries using JSX (see #21699 (comment)). Using the React namespace would defeat that purpose.
Some comments on the meeting notes #51344:
There have been long standing issues that we can't return every possible type from function components (
It should work. However, class components are already properly typed because we can hook into |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Closes #21699
Closes #14729
Enables closing DefinitelyTyped/DefinitelyTyped#18051 and DefinitelyTyped/DefinitelyTyped#18912
Quick terminology intro:
Today, function components that return anything but
null | JSX.Element
are not allowed as element types in React. For example,const Component = () => 42; <Component />
would be rejected by the type-checker because 42 is not a valid JSX element. Note that this return value would be perfectly fine in class components.However, in React, components can return a
ReactNode
. That type includesnumber | string | Iterable<ReactNode> | undefined
(and will likely includePromise<ReactNode>
in the future).Prior attempts at fixing this issue tried to lookup the type of the JSX factory to determine what correct element types are. These attempts were abandoned due to severe perf regressions.
Instead of looking up the type of the JSX factory I'm proposing looking up the type of
JSX.ElementType
. This allows libraries to explicitly define what can be used as an element type. IfJSX.ElementType
does not exist, we fallback to the current behavior.In React,
@types/react
would declareJSX.ElementType
as follows (see tests for concrete usage):Alternatives:
A. We already have a dedicated type for JSX class components. Instead of allowing to customize the whole element type, we could just introduce
JSX.ElementFunction
which would work similar toJSX.ElementClass
B. Alias
JSX.Element
toany
TODO: