diff --git a/internal/checker/relater.go b/internal/checker/relater.go
index e649e25b10..efd9f52b3d 100644
--- a/internal/checker/relater.go
+++ b/internal/checker/relater.go
@@ -2729,7 +2729,19 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b
}
checkTypes = reducedTarget.Distributed()
}
- for _, prop := range r.c.getPropertiesOfType(source) {
+ properties := r.c.getPropertiesOfType(source)
+ if isComparingJsxAttributes {
+ // Strada's insertion-ordered spread puts synthetic JSX children before explicit attributes.
+ for i, prop := range properties {
+ if i != 0 && prop.ValueDeclaration != nil && ast.IsPropertySignatureDeclaration(prop.ValueDeclaration) && ast.IsJsxAttributes(prop.ValueDeclaration.Parent) {
+ properties = slices.Clone(properties)
+ copy(properties[1:i+1], properties[:i])
+ properties[0] = prop
+ break
+ }
+ }
+ }
+ for _, prop := range properties {
if shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop) {
if !r.c.isKnownProperty(reducedTarget, prop.Name, isComparingJsxAttributes) {
if reportErrors {
diff --git a/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.symbols b/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.symbols
new file mode 100644
index 0000000000..c8570b582f
--- /dev/null
+++ b/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.symbols
@@ -0,0 +1,96 @@
+//// [tests/cases/compiler/externalLibraryMultilineJsxTsIgnore.ts] ////
+
+=== /node_modules/pkg/exports.d.ts ===
+export { x, y } from "./src/ui";
+>x : Symbol(x, Decl(exports.d.ts, 0, 8))
+>y : Symbol(y, Decl(exports.d.ts, 0, 11))
+
+=== /node_modules/pkg/src/ui.tsx ===
+declare global {
+>global : Symbol(global, Decl(ui.tsx, 0, 0))
+
+ namespace JSX {
+>JSX : Symbol(JSX, Decl(ui.tsx, 0, 16))
+
+ interface Element {}
+>Element : Symbol(Element, Decl(ui.tsx, 1, 19))
+
+ interface IntrinsicAttributes {}
+>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(ui.tsx, 2, 28))
+
+ interface ElementChildrenAttribute {
+>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(ui.tsx, 3, 40))
+
+ children: {};
+>children : Symbol(ElementChildrenAttribute.children, Decl(ui.tsx, 4, 44))
+ }
+ interface IntrinsicElements {
+>IntrinsicElements : Symbol(IntrinsicElements, Decl(ui.tsx, 6, 9))
+
+ div: {};
+>div : Symbol(IntrinsicElements.div, Decl(ui.tsx, 7, 37))
+ }
+ }
+}
+
+declare const Component: (props: {}) => JSX.Element;
+>Component : Symbol(Component, Decl(ui.tsx, 13, 13))
+>props : Symbol(props, Decl(ui.tsx, 13, 26))
+>JSX : Symbol(JSX, Decl(ui.tsx, 0, 16))
+>Element : Symbol(JSX.Element, Decl(ui.tsx, 1, 19))
+
+export const x = (
+>x : Symbol(x, Decl(ui.tsx, 15, 12))
+
+ // @ts-ignore
+ Component : Symbol(Component, Decl(ui.tsx, 13, 13))
+
+ invalid=""
+>invalid : Symbol(invalid, Decl(ui.tsx, 17, 14))
+
+ >
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(ui.tsx, 7, 37))
+
+
+>Component : Symbol(Component, Decl(ui.tsx, 13, 13))
+
+);
+
+export const y = (
+>y : Symbol(y, Decl(ui.tsx, 24, 12))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(ui.tsx, 7, 37))
+
+ {/* @ts-ignore */}
+
Component : Symbol(Component, Decl(ui.tsx, 13, 13))
+
+ invalid=""
+>invalid : Symbol(invalid, Decl(ui.tsx, 27, 18))
+
+ >
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(ui.tsx, 7, 37))
+
+
+>Component : Symbol(Component, Decl(ui.tsx, 13, 13))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(ui.tsx, 7, 37))
+
+);
+
+=== /index.ts ===
+import { x, y } from "pkg";
+>x : Symbol(x, Decl(index.ts, 0, 8))
+>y : Symbol(y, Decl(index.ts, 0, 11))
+
+x;
+>x : Symbol(x, Decl(index.ts, 0, 8))
+
+y;
+>y : Symbol(y, Decl(index.ts, 0, 11))
+
diff --git a/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.types b/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.types
new file mode 100644
index 0000000000..e3ace77f01
--- /dev/null
+++ b/testdata/baselines/reference/compiler/externalLibraryMultilineJsxTsIgnore.types
@@ -0,0 +1,92 @@
+//// [tests/cases/compiler/externalLibraryMultilineJsxTsIgnore.ts] ////
+
+=== /node_modules/pkg/exports.d.ts ===
+export { x, y } from "./src/ui";
+>x : JSX.Element
+>y : JSX.Element
+
+=== /node_modules/pkg/src/ui.tsx ===
+declare global {
+>global : any
+
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicAttributes {}
+ interface ElementChildrenAttribute {
+ children: {};
+>children : {}
+ }
+ interface IntrinsicElements {
+ div: {};
+>div : {}
+ }
+ }
+}
+
+declare const Component: (props: {}) => JSX.Element;
+>Component : (props: {}) => JSX.Element
+>props : {}
+>JSX : any
+
+export const x = (
+>x : JSX.Element
+>( // @ts-ignore ) : JSX.Element
+
+ // @ts-ignore
+ : JSX.Element
+>Component : (props: {}) => JSX.Element
+
+ invalid=""
+>invalid : string
+
+ >
+
+> : JSX.Element
+>div : any
+
+
+>Component : (props: {}) => JSX.Element
+
+);
+
+export const y = (
+>y : JSX.Element
+>( ) : JSX.Element
+
+
+>
: JSX.Element
+>div : any
+
+ {/* @ts-ignore */}
+
: JSX.Element
+>Component : (props: {}) => JSX.Element
+
+ invalid=""
+>invalid : string
+
+ >
+
+> : JSX.Element
+>div : any
+
+
+>Component : (props: {}) => JSX.Element
+
+
+>div : any
+
+);
+
+=== /index.ts ===
+import { x, y } from "pkg";
+>x : JSX.Element
+>y : JSX.Element
+
+x;
+>x : JSX.Element
+
+y;
+>y : JSX.Element
+
diff --git a/testdata/tests/cases/compiler/externalLibraryMultilineJsxTsIgnore.ts b/testdata/tests/cases/compiler/externalLibraryMultilineJsxTsIgnore.ts
new file mode 100644
index 0000000000..ada88098f8
--- /dev/null
+++ b/testdata/tests/cases/compiler/externalLibraryMultilineJsxTsIgnore.ts
@@ -0,0 +1,58 @@
+// @strict: true
+// @skipLibCheck: true
+// @jsx: preserve
+// @module: esnext
+// @moduleResolution: bundler
+// @noEmit: true
+
+// @filename: /node_modules/pkg/package.json
+{
+ "name": "pkg",
+ "version": "1.0.0",
+ "types": "./exports.d.ts"
+}
+
+// @filename: /node_modules/pkg/exports.d.ts
+export { x, y } from "./src/ui";
+
+// @filename: /node_modules/pkg/src/ui.tsx
+declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicAttributes {}
+ interface ElementChildrenAttribute {
+ children: {};
+ }
+ interface IntrinsicElements {
+ div: {};
+ }
+ }
+}
+
+declare const Component: (props: {}) => JSX.Element;
+
+export const x = (
+ // @ts-ignore
+
+
+
+);
+
+export const y = (
+
+ {/* @ts-ignore */}
+
+
+
+
+);
+
+// @filename: /index.ts
+import { x, y } from "pkg";
+
+x;
+y;