diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 6340f6386a8..267da572737 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -15398,7 +15398,10 @@ namespace ts {
if (hasSpreadAnyType) {
return anyType;
}
- return typeToIntersect && spread !== emptyObjectType ? getIntersectionType([typeToIntersect, spread]) : (typeToIntersect || spread);
+ if (typeToIntersect && spread !== emptyObjectType) {
+ return getIntersectionType([typeToIntersect, spread]);
+ }
+ return typeToIntersect || (spread === emptyObjectType ? createJsxAttributesType() : spread);
/**
* Create anonymous type from given attributes symbol table.
diff --git a/tests/baselines/reference/tsxAttributeResolution12.errors.txt b/tests/baselines/reference/tsxAttributeResolution12.errors.txt
index 7ee4670dc65..3113eb833ba 100644
--- a/tests/baselines/reference/tsxAttributeResolution12.errors.txt
+++ b/tests/baselines/reference/tsxAttributeResolution12.errors.txt
@@ -3,6 +3,7 @@ tests/cases/conformance/jsx/file.tsx(25,10): error TS2322: Type '{}' is not assi
Property 'reqd' is missing in type '{}'.
tests/cases/conformance/jsx/file.tsx(28,10): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
Type '{}' is not assignable to type '{ reqd: any; }'.
+ Property 'reqd' is missing in type '{}'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -54,5 +55,6 @@ tests/cases/conformance/jsx/file.tsx(28,10): error TS2322: Type '{}' is not assi
~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ reqd: any; }'.
+!!! error TS2322: Property 'reqd' is missing in type '{}'.
\ No newline at end of file
diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.js b/tests/baselines/reference/tsxAttributesHasInferrableIndex.js
new file mode 100644
index 00000000000..0cc23d34c40
--- /dev/null
+++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.js
@@ -0,0 +1,31 @@
+//// [tsxAttributesHasInferrableIndex.tsx]
+type AttributeValue = number | string | Date | boolean;
+interface Attributes {
+ [key: string]: AttributeValue;
+}
+function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) {
+ return name;
+}
+namespace createElement.JSX {
+ type Element = string;
+}
+
+function Button(attributes: Attributes | undefined, contents: string[]) {
+ return '';
+}
+const b =
+
+
+//// [tsxAttributesHasInferrableIndex.js]
+"use strict";
+function createElement(name, attributes) {
+ var contents = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ contents[_i - 2] = arguments[_i];
+ }
+ return name;
+}
+function Button(attributes, contents) {
+ return '';
+}
+var b = createElement(Button, null);
diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols b/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols
new file mode 100644
index 00000000000..f36c8ec1de8
--- /dev/null
+++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols
@@ -0,0 +1,43 @@
+=== tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx ===
+type AttributeValue = number | string | Date | boolean;
+>AttributeValue : Symbol(AttributeValue, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 0))
+>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
+
+interface Attributes {
+>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55))
+
+ [key: string]: AttributeValue;
+>key : Symbol(key, Decl(tsxAttributesHasInferrableIndex.tsx, 2, 5))
+>AttributeValue : Symbol(AttributeValue, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 0))
+}
+function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) {
+>createElement : Symbol(createElement, Decl(tsxAttributesHasInferrableIndex.tsx, 3, 1), Decl(tsxAttributesHasInferrableIndex.tsx, 6, 1))
+>name : Symbol(name, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 23))
+>attributes : Symbol(attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 36))
+>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55))
+>contents : Symbol(contents, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 72))
+
+ return name;
+>name : Symbol(name, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 23))
+}
+namespace createElement.JSX {
+>createElement : Symbol(createElement, Decl(tsxAttributesHasInferrableIndex.tsx, 3, 1), Decl(tsxAttributesHasInferrableIndex.tsx, 6, 1))
+>JSX : Symbol(JSX, Decl(tsxAttributesHasInferrableIndex.tsx, 7, 24))
+
+ type Element = string;
+>Element : Symbol(Element, Decl(tsxAttributesHasInferrableIndex.tsx, 7, 29))
+}
+
+function Button(attributes: Attributes | undefined, contents: string[]) {
+>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1))
+>attributes : Symbol(attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 11, 16))
+>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55))
+>contents : Symbol(contents, Decl(tsxAttributesHasInferrableIndex.tsx, 11, 51))
+
+ return '';
+}
+const b =
+>b : Symbol(b, Decl(tsxAttributesHasInferrableIndex.tsx, 14, 5))
+>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1))
+>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1))
+
diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.types b/tests/baselines/reference/tsxAttributesHasInferrableIndex.types
new file mode 100644
index 00000000000..91e577a07b4
--- /dev/null
+++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.types
@@ -0,0 +1,45 @@
+=== tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx ===
+type AttributeValue = number | string | Date | boolean;
+>AttributeValue : AttributeValue
+>Date : Date
+
+interface Attributes {
+>Attributes : Attributes
+
+ [key: string]: AttributeValue;
+>key : string
+>AttributeValue : AttributeValue
+}
+function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) {
+>createElement : (name: string, attributes: Attributes | undefined, ...contents: string[]) => string
+>name : string
+>attributes : Attributes | undefined
+>Attributes : Attributes
+>contents : string[]
+
+ return name;
+>name : string
+}
+namespace createElement.JSX {
+>createElement : (name: string, attributes: Attributes | undefined, ...contents: string[]) => string
+>JSX : any
+
+ type Element = string;
+>Element : string
+}
+
+function Button(attributes: Attributes | undefined, contents: string[]) {
+>Button : (attributes: Attributes | undefined, contents: string[]) => string
+>attributes : Attributes | undefined
+>Attributes : Attributes
+>contents : string[]
+
+ return '';
+>'' : ""
+}
+const b =
+>b : any
+> : any
+>Button : (attributes: Attributes | undefined, contents: string[]) => string
+>Button : (attributes: Attributes | undefined, contents: string[]) => string
+
diff --git a/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx b/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx
new file mode 100644
index 00000000000..d5f43b0e712
--- /dev/null
+++ b/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx
@@ -0,0 +1,18 @@
+// @strict: true
+// @jsx: react
+// @jsxFactory: createElement
+type AttributeValue = number | string | Date | boolean;
+interface Attributes {
+ [key: string]: AttributeValue;
+}
+function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) {
+ return name;
+}
+namespace createElement.JSX {
+ type Element = string;
+}
+
+function Button(attributes: Attributes | undefined, contents: string[]) {
+ return '';
+}
+const b =