-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
add jsx fragments to callLikeExpression #59933
Conversation
Looks like you're introducing a change to the public API surface area. If this includes breaking changes, please document them on our wiki's API Breaking Changes page. Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up. |
@typescript-bot test it |
Hey @iisaduan, the results of running the DT tests are ready. Everything looks the same! |
@iisaduan Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
@iisaduan Here are the results of running the user tests with tsc comparing Everything looks good! |
export type JsxCallLike = | ||
| JsxOpeningLikeElement | ||
| JsxOpeningFragment; |
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.
wouldnt it make sense to include JsxOpeningFragment
as part of JsxOpeningLikeElement
?
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.
@iisaduan can you address that suggestion?
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.
Apologies for the delay in response. It's a good question and I wanted something detailed for PR description.
TLDR keeping a type that has only opening element
and self closing element
, is still beneficial, and adding JsxOpeningFragment
to JsxOpeningLikeElement
requires a much bigger change than is needed to add this fragment type check. The biggest reason is because this add causes crashes in expression checking. We would either need to rework what fragments are, in a way that is making them almost identical to an JsxOpeningElement
, or we would need to update the majority of places JsxOpeningLikeElement
is referenced to ignore fragments anyway (and if we don't want to ignore them, we'd need to handle fragments specially, which could cause us to do redundant/unnecessary work).
In my first iteration of this PR, I did try to add fragments to openingLike
, and the biggest issue was that we run into crashes during expression checking (probably due to several series of no longer correct assertions). Since the fragment check is now fully added, I tried again to fix these crashes over the last day or so, but I still ran into layers of them, so it just ends up being much more work than is necessary for this type check.
Also regarding the use of JsxOpeningLikeElement
-- they have many more checks than what we need to check fragments, so adding fragments would require us to then ignore fragments in many uses of openinglike. For example, after this PR, just in checker
, there are ~30 functions that would still error because of fragment incompatibilty with what JsxOpeningLikeElement
is currently. These functions would almost always be updated to ignore fragments anyways, since ~20 are related to checking tagName
or attributes
. While the rest may have checks applicable to fragments, they aren't performing any different checks than what we already do (so we should probably ignore fragments because we don't need to do the work for them again). This is without taking into account other parts of the compiler/services, and anyone else using JsxOpeningLikeElement
@iisaduan Here are the results of running the top 400 repos with tsc comparing Something interesting changed - please have a look. Details
|
src/compiler/checker.ts
Outdated
const errorNode = isJsxOpeningFragment(node) ? node : node.tagName; | ||
const errorEntityName = isJsxOpeningFragment(node) ? "Fragment" : entityNameToString(node.tagName); | ||
const diag = createDiagnosticForNode(errorNode, Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, errorEntityName, absoluteMinArgCount, entityNameToString(factory), maxParamCount); | ||
const tagNameDeclaration = isJsxOpeningFragment(node) ? getJSXFragmentType(node).symbol.valueDeclaration : getSymbolAtLocation(node.tagName)?.valueDeclaration; |
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.
Rather than writing Tag 'Fragment' expects at least...
, should we specialize the message to just Fragments expect at least...
for the fragment case? Since they're really not named tags, per sey.
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.
I ended up reverting this change. I did some testing, and even with proper checking of fragments in the rest of checkTagNameDoesNotExpectTooManyArguments
, it doesn't seem possible to hit this error message with a fragment. Hitting this error message requires attributes to be passed in through the tag (example <TagName x={/*stuff*/}>
). For just an opening element, if there are no attributes in the tag (<TagName>
), we won't ever hit this error because we issue missing property or not assignable errors instead. So even if Fragment
is defined to always take multiple arguments, we won't ever get this error
Typescript 5.7 will fail unless usage of RaxFragment is explicit, with an import of it and a `/** @jsxFrag RaxFragment */` pragma at the top of the file. This PR adds that. RaxFragment also needs to have an exported value. I wasn't sure what to use here so I copied preact, since preact is used in the Typescript handbook as an example: ```ts export const RaxFragment: FunctionComponent<{}> ``` Notably, though, the preact source has a comment indicating that *they're* not sure of the correct type either. Here is the Typescript 5.7 PR that made this error appear: microsoft/TypeScript#59933
It now requires an explicit import of React in order to use JSX fragments. Here is the Typescript 5.7 PR that introduced this error: microsoft/TypeScript#59933
It now requires an explicit import of React in order to use JSX fragments. Here is the Typescript 5.7 PR that introduced this error: microsoft/TypeScript#59933
This PR adds type checking to the children of JSX fragments. Fixes #50429.
JsxOpeningFragment
toCallLikeExpression
by definingJsxCallLike
.JsxOpeningFragment
is not added toJsxOpenlingLikeFragment
because it requires many more changes than necessary for this typecheck, and causes crashes in expression checking. More details here.NodeLinks
:jsxFragmentType
to store the type of the fragment at theSourceFile
level, since a different fragment factory can be referenced per file.resolvedJsxElementAllAttributesType
andresolvedIndexInfo
(since both have been unused since at least 2018??)isCallLikeExpression
to account forInstanceOfExpression
TS2876: Using JSX fragments requires fragment factory {0} to be in scope, but it could not be found.
We previously did not issue an error if a fragment factory was set through a pragma or compiler option, and the specified factory could not be resolved.