From 7fcfd01ec36f8fd209432e139a50d1c3e9469fca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:20:01 +0000 Subject: [PATCH] Fix regression: only apply contextual type for fragment children, not regular JSX elements Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/checker.ts | 27 +++++++++---------- ...FactoryReference(jsx=react-jsx).errors.txt | 5 +++- ...toryReference(jsx=react-jsxdev).errors.txt | 5 +++- ...formCustomImport(jsx=react-jsx).errors.txt | 5 +++- ...mCustomImport(jsx=react-jsxdev).errors.txt | 5 +++- ...stomImportPragma(jsx=react-jsx).errors.txt | 5 +++- ...mImportPragma(jsx=react-jsxdev).errors.txt | 5 +++- 7 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9bafc0c9838..f3cf9c10ff3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -33791,25 +33791,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (isJsxElement(parent) && parent.openingElement === openingLikeElement || isJsxFragment(parent) && parent.openingFragment === openingLikeElement) && getSemanticJsxChildren(parent.children).length > 0 ) { - // Compute contextual type for children before checking them + // Compute contextual type for fragment children before checking them let childrenContextualType: Type | undefined; - if (jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { - let contextualType: Type | undefined; - if (isJsxOpeningElement(openingLikeElement)) { - contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes, /*contextFlags*/ undefined); + if (isJsxOpeningFragment(openingLikeElement) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { + // For fragments, get the props type from the Fragment factory's signature + const fragmentType = getJSXFragmentType(openingLikeElement); + const signatures = getSignaturesOfType(fragmentType, SignatureKind.Call); + if (signatures.length > 0) { + const contextualType = getTypeOfFirstParameterOfSignature(signatures[0]); + childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); } - else if (isJsxOpeningFragment(openingLikeElement)) { - // For fragments, get the props type from the Fragment factory's signature - const fragmentType = getJSXFragmentType(openingLikeElement); - const signatures = getSignaturesOfType(fragmentType, SignatureKind.Call); - if (signatures.length > 0) { - contextualType = getTypeOfFirstParameterOfSignature(signatures[0]); - } - } - childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); } - // Check children with contextual type + // Check children with contextual type (only for fragments) const childrenTypes: Type[] = checkJsxChildren(parent, checkMode, childrenContextualType); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { @@ -33819,6 +33813,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (explicitlySpecifyChildrenAttribute) { error(attributeParent, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); } + + const contextualType = isJsxOpeningElement(openingLikeElement) ? getApparentTypeOfContextualType(openingLikeElement.attributes, /*contextFlags*/ undefined) : undefined; + const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process const childrenPropSymbol = createSymbol(SymbolFlags.Property, jsxChildrenPropertyName); childrenPropSymbol.links.type = childrenTypes.length === 1 ? childrenTypes[0] : diff --git a/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsx).errors.txt b/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsx).errors.txt index 453fbd038e2..c8caaefa362 100644 --- a/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsx).errors.txt +++ b/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsx).errors.txt @@ -1,12 +1,15 @@ jsxFragmentFactoryReference.tsx(3,9): error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +jsxFragmentFactoryReference.tsx(3,9): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. -==== jsxFragmentFactoryReference.tsx (1 errors) ==== +==== jsxFragmentFactoryReference.tsx (2 errors) ==== export class LoggedOut { content = () => ( <> ~~ !!! error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. ) } \ No newline at end of file diff --git a/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsxdev).errors.txt b/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsxdev).errors.txt index 7529f71c4d5..16bb6f5a544 100644 --- a/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsxdev).errors.txt +++ b/tests/baselines/reference/jsxFragmentFactoryReference(jsx=react-jsxdev).errors.txt @@ -1,12 +1,15 @@ jsxFragmentFactoryReference.tsx(3,9): error TS2875: This JSX tag requires the module path 'react/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +jsxFragmentFactoryReference.tsx(3,9): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. -==== jsxFragmentFactoryReference.tsx (1 errors) ==== +==== jsxFragmentFactoryReference.tsx (2 errors) ==== export class LoggedOut { content = () => ( <> ~~ !!! error TS2875: This JSX tag requires the module path 'react/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. ) } \ No newline at end of file diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).errors.txt b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).errors.txt index 248540ed384..2b8fbaf4e46 100644 --- a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).errors.txt +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).errors.txt @@ -1,11 +1,14 @@ jsxJsxsCjsTransformCustomImport.tsx(2,11): error TS2875: This JSX tag requires the module path 'preact/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +jsxJsxsCjsTransformCustomImport.tsx(2,11): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. -==== jsxJsxsCjsTransformCustomImport.tsx (1 errors) ==== +==== jsxJsxsCjsTransformCustomImport.tsx (2 errors) ==== /// const a = <> ~~ !!! error TS2875: This JSX tag requires the module path 'preact/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found.

text
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).errors.txt b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).errors.txt index e66480f8dce..31af5093deb 100644 --- a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).errors.txt +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).errors.txt @@ -1,11 +1,14 @@ jsxJsxsCjsTransformCustomImport.tsx(2,11): error TS2875: This JSX tag requires the module path 'preact/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +jsxJsxsCjsTransformCustomImport.tsx(2,11): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. -==== jsxJsxsCjsTransformCustomImport.tsx (1 errors) ==== +==== jsxJsxsCjsTransformCustomImport.tsx (2 errors) ==== /// const a = <> ~~ !!! error TS2875: This JSX tag requires the module path 'preact/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found.

text
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).errors.txt b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).errors.txt index c37e010cab8..7155c43a5da 100644 --- a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).errors.txt +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).errors.txt @@ -1,4 +1,5 @@ preact.tsx(3,11): error TS2875: This JSX tag requires the module path 'preact/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +preact.tsx(3,11): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. ==== react.tsx (0 errors) ==== @@ -12,12 +13,14 @@ preact.tsx(3,11): error TS2875: This JSX tag requires the module path 'preact/js export {}; -==== preact.tsx (1 errors) ==== +==== preact.tsx (2 errors) ==== /// /* @jsxImportSource preact */ const a = <> ~~ !!! error TS2875: This JSX tag requires the module path 'preact/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found.

text
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).errors.txt b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).errors.txt index 79e8e02a87b..ad4bb3c20b1 100644 --- a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).errors.txt +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).errors.txt @@ -1,4 +1,5 @@ preact.tsx(3,11): error TS2875: This JSX tag requires the module path 'preact/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. +preact.tsx(3,11): error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found. ==== react.tsx (0 errors) ==== @@ -12,12 +13,14 @@ preact.tsx(3,11): error TS2875: This JSX tag requires the module path 'preact/js export {}; -==== preact.tsx (1 errors) ==== +==== preact.tsx (2 errors) ==== /// /* @jsxImportSource preact */ const a = <> ~~ !!! error TS2875: This JSX tag requires the module path 'preact/jsx-dev-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + ~~ +!!! error TS2879: Using JSX fragments requires fragment factory 'React' to be in scope, but it could not be found.

text