diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index bd576cecbfda6..48103dafb9102 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -16794,7 +16794,7 @@ namespace ts {
function *generateJsxAttributes(node: JsxAttributes): ElaborationIterator {
if (!length(node.properties)) return;
for (const prop of node.properties) {
- if (isJsxSpreadAttribute(prop)) continue;
+ if (isJsxSpreadAttribute(prop) || isHyphenatedJsxName(idText(prop.name))) continue;
yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: getStringLiteralType(idText(prop.name)) };
}
}
@@ -17355,7 +17355,7 @@ namespace ts {
}
function isIgnoredJsxProperty(source: Type, sourceProp: Symbol) {
- return getObjectFlags(source) & ObjectFlags.JsxAttributes && !isUnhyphenatedJsxName(sourceProp.escapedName);
+ return getObjectFlags(source) & ObjectFlags.JsxAttributes && isHyphenatedJsxName(sourceProp.escapedName);
}
function getNormalizedType(type: Type, writing: boolean): Type {
@@ -26585,8 +26585,8 @@ namespace ts {
return getJsxElementTypeAt(node) || anyType;
}
- function isUnhyphenatedJsxName(name: string | __String) {
- return !stringContains(name as string, "-");
+ function isHyphenatedJsxName(name: string | __String) {
+ return stringContains(name as string, "-");
}
/**
@@ -27127,7 +27127,7 @@ namespace ts {
if (getPropertyOfObjectType(targetType, name) ||
getApplicableIndexInfoForName(targetType, name) ||
isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) ||
- isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
+ isComparingJsxAttributes && isHyphenatedJsxName(name)) {
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
return true;
}
diff --git a/tests/baselines/reference/ignoredJsxAttributes.errors.txt b/tests/baselines/reference/ignoredJsxAttributes.errors.txt
new file mode 100644
index 0000000000000..db428fd588fc9
--- /dev/null
+++ b/tests/baselines/reference/ignoredJsxAttributes.errors.txt
@@ -0,0 +1,32 @@
+tests/cases/compiler/ignoredJsxAttributes.tsx(16,5): error TS2322: Type 'number' is not assignable to type 'string'.
+tests/cases/compiler/ignoredJsxAttributes.tsx(20,11): error TS2741: Property 'foo' is missing in type '{ bar: string; "data-yadda": number; }' but required in type 'Props'.
+
+
+==== tests/cases/compiler/ignoredJsxAttributes.tsx (2 errors) ====
+ ///
+
+ // Repro from #44797
+
+ import * as React from "react";
+
+ interface Props {
+ foo: string;
+ [dataProp: string]: string;
+ }
+
+ declare function Yadda(props: Props): JSX.Element;
+
+ let props: Props = {
+ foo: "",
+ "data-yadda": 42, // Error
+ ~~~~~~~~~~~~
+!!! error TS2322: Type 'number' is not assignable to type 'string'.
+!!! related TS6501 tests/cases/compiler/ignoredJsxAttributes.tsx:9:5: The expected type comes from this index signature.
+ };
+
+ let x1 = ;
+ let x2 = ; // Error
+ ~~~~~
+!!! error TS2741: Property 'foo' is missing in type '{ bar: string; "data-yadda": number; }' but required in type 'Props'.
+!!! related TS2728 tests/cases/compiler/ignoredJsxAttributes.tsx:8:5: 'foo' is declared here.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/ignoredJsxAttributes.js b/tests/baselines/reference/ignoredJsxAttributes.js
new file mode 100644
index 0000000000000..4aa89833cab09
--- /dev/null
+++ b/tests/baselines/reference/ignoredJsxAttributes.js
@@ -0,0 +1,35 @@
+//// [ignoredJsxAttributes.tsx]
+///
+
+// Repro from #44797
+
+import * as React from "react";
+
+interface Props {
+ foo: string;
+ [dataProp: string]: string;
+}
+
+declare function Yadda(props: Props): JSX.Element;
+
+let props: Props = {
+ foo: "",
+ "data-yadda": 42, // Error
+};
+
+let x1 = ;
+let x2 = ; // Error
+
+
+//// [ignoredJsxAttributes.js]
+"use strict";
+///
+exports.__esModule = true;
+// Repro from #44797
+var React = require("react");
+var props = {
+ foo: "",
+ "data-yadda": 42
+};
+var x1 = React.createElement(Yadda, { foo: "hello", "data-yadda": 42 });
+var x2 = React.createElement(Yadda, { bar: "hello", "data-yadda": 42 }); // Error
diff --git a/tests/baselines/reference/ignoredJsxAttributes.symbols b/tests/baselines/reference/ignoredJsxAttributes.symbols
new file mode 100644
index 0000000000000..3e7db8969c7ad
--- /dev/null
+++ b/tests/baselines/reference/ignoredJsxAttributes.symbols
@@ -0,0 +1,49 @@
+=== tests/cases/compiler/ignoredJsxAttributes.tsx ===
+///
+
+// Repro from #44797
+
+import * as React from "react";
+>React : Symbol(React, Decl(ignoredJsxAttributes.tsx, 4, 6))
+
+interface Props {
+>Props : Symbol(Props, Decl(ignoredJsxAttributes.tsx, 4, 31))
+
+ foo: string;
+>foo : Symbol(Props.foo, Decl(ignoredJsxAttributes.tsx, 6, 17))
+
+ [dataProp: string]: string;
+>dataProp : Symbol(dataProp, Decl(ignoredJsxAttributes.tsx, 8, 5))
+}
+
+declare function Yadda(props: Props): JSX.Element;
+>Yadda : Symbol(Yadda, Decl(ignoredJsxAttributes.tsx, 9, 1))
+>props : Symbol(props, Decl(ignoredJsxAttributes.tsx, 11, 23))
+>Props : Symbol(Props, Decl(ignoredJsxAttributes.tsx, 4, 31))
+>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12))
+>Element : Symbol(JSX.Element, Decl(react16.d.ts, 2494, 23))
+
+let props: Props = {
+>props : Symbol(props, Decl(ignoredJsxAttributes.tsx, 13, 3))
+>Props : Symbol(Props, Decl(ignoredJsxAttributes.tsx, 4, 31))
+
+ foo: "",
+>foo : Symbol(foo, Decl(ignoredJsxAttributes.tsx, 13, 20))
+
+ "data-yadda": 42, // Error
+>"data-yadda" : Symbol("data-yadda", Decl(ignoredJsxAttributes.tsx, 14, 12))
+
+};
+
+let x1 = ;
+>x1 : Symbol(x1, Decl(ignoredJsxAttributes.tsx, 18, 3))
+>Yadda : Symbol(Yadda, Decl(ignoredJsxAttributes.tsx, 9, 1))
+>foo : Symbol(foo, Decl(ignoredJsxAttributes.tsx, 18, 15))
+>data-yadda : Symbol(data-yadda, Decl(ignoredJsxAttributes.tsx, 18, 27))
+
+let x2 = ; // Error
+>x2 : Symbol(x2, Decl(ignoredJsxAttributes.tsx, 19, 3))
+>Yadda : Symbol(Yadda, Decl(ignoredJsxAttributes.tsx, 9, 1))
+>bar : Symbol(bar, Decl(ignoredJsxAttributes.tsx, 19, 15))
+>data-yadda : Symbol(data-yadda, Decl(ignoredJsxAttributes.tsx, 19, 27))
+
diff --git a/tests/baselines/reference/ignoredJsxAttributes.types b/tests/baselines/reference/ignoredJsxAttributes.types
new file mode 100644
index 0000000000000..ec8500a13e546
--- /dev/null
+++ b/tests/baselines/reference/ignoredJsxAttributes.types
@@ -0,0 +1,51 @@
+=== tests/cases/compiler/ignoredJsxAttributes.tsx ===
+///
+
+// Repro from #44797
+
+import * as React from "react";
+>React : typeof React
+
+interface Props {
+ foo: string;
+>foo : string
+
+ [dataProp: string]: string;
+>dataProp : string
+}
+
+declare function Yadda(props: Props): JSX.Element;
+>Yadda : (props: Props) => JSX.Element
+>props : Props
+>JSX : any
+
+let props: Props = {
+>props : Props
+>{ foo: "", "data-yadda": 42, // Error} : { foo: string; "data-yadda": number; }
+
+ foo: "",
+>foo : string
+>"" : ""
+
+ "data-yadda": 42, // Error
+>"data-yadda" : number
+>42 : 42
+
+};
+
+let x1 = ;
+>x1 : JSX.Element
+> : JSX.Element
+>Yadda : (props: Props) => JSX.Element
+>foo : string
+>data-yadda : number
+>42 : 42
+
+let x2 = ; // Error
+>x2 : JSX.Element
+> : JSX.Element
+>Yadda : (props: Props) => JSX.Element
+>bar : string
+>data-yadda : number
+>42 : 42
+
diff --git a/tests/baselines/reference/tsxAttributeResolution7.errors.txt b/tests/baselines/reference/tsxAttributeResolution7.errors.txt
index f36d8eaa0ad8f..307aa54df5f47 100644
--- a/tests/baselines/reference/tsxAttributeResolution7.errors.txt
+++ b/tests/baselines/reference/tsxAttributeResolution7.errors.txt
@@ -1,4 +1,6 @@
-tests/cases/conformance/jsx/file.tsx(9,8): error TS2322: Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/jsx/file.tsx(9,2): error TS2322: Type '{ "data-foo": number; }' is not assignable to type '{ "data-foo"?: string; }'.
+ Types of property '"data-foo"' are incompatible.
+ Type 'number' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -11,9 +13,10 @@ tests/cases/conformance/jsx/file.tsx(9,8): error TS2322: Type 'number' is not as
// Error
;
- ~~~~~~~~
-!!! error TS2322: Type 'number' is not assignable to type 'string'.
-!!! related TS6500 tests/cases/conformance/jsx/file.tsx:4:12: The expected type comes from property 'data-foo' which is declared here on type '{ "data-foo"?: string; }'
+ ~~~~~
+!!! error TS2322: Type '{ "data-foo": number; }' is not assignable to type '{ "data-foo"?: string; }'.
+!!! error TS2322: Types of property '"data-foo"' are incompatible.
+!!! error TS2322: Type 'number' is not assignable to type 'string'.
// OK
;
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentOverload4.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentOverload4.errors.txt
index 2513a3ba14c1c..57ddd4acd2253 100644
--- a/tests/baselines/reference/tsxStatelessFunctionComponentOverload4.errors.txt
+++ b/tests/baselines/reference/tsxStatelessFunctionComponentOverload4.errors.txt
@@ -31,9 +31,11 @@ tests/cases/conformance/jsx/file.tsx(17,13): error TS2769: No overload matches t
Type '{ yy: boolean; yy1: string; }' is not assignable to type '{ yy: number; yy1: string; }'.
Types of property 'yy' are incompatible.
Type 'boolean' is not assignable to type 'number'.
-tests/cases/conformance/jsx/file.tsx(25,12): error TS2769: No overload matches this call.
+tests/cases/conformance/jsx/file.tsx(25,13): error TS2769: No overload matches this call.
Overload 1 of 2, '(j: { "extra-data": string; }): Element', gave the following error.
- Type 'boolean' is not assignable to type 'string'.
+ Type '{ "extra-data": true; }' is not assignable to type '{ "extra-data": string; }'.
+ Types of property '"extra-data"' are incompatible.
+ Type 'boolean' is not assignable to type 'string'.
Overload 2 of 2, '(n: { yy: string; direction?: number; }): Element', gave the following error.
Property 'yy' is missing in type '{ "extra-data": true; }' but required in type '{ yy: string; direction?: number; }'.
tests/cases/conformance/jsx/file.tsx(26,12): error TS2769: No overload matches this call.
@@ -142,13 +144,14 @@ tests/cases/conformance/jsx/file.tsx(36,12): error TS2769: No overload matches t
// Error
const d1 =
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~~~~~~~~~~~~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(j: { "extra-data": string; }): Element', gave the following error.
-!!! error TS2769: Type 'boolean' is not assignable to type 'string'.
+!!! error TS2769: Type '{ "extra-data": true; }' is not assignable to type '{ "extra-data": string; }'.
+!!! error TS2769: Types of property '"extra-data"' are incompatible.
+!!! error TS2769: Type 'boolean' is not assignable to type 'string'.
!!! error TS2769: Overload 2 of 2, '(n: { yy: string; direction?: number; }): Element', gave the following error.
!!! error TS2769: Property 'yy' is missing in type '{ "extra-data": true; }' but required in type '{ yy: string; direction?: number; }'.
-!!! related TS6500 tests/cases/conformance/jsx/file.tsx:21:38: The expected type comes from property 'extra-data' which is declared here on type 'IntrinsicAttributes & { "extra-data": string; }'
!!! related TS2728 tests/cases/conformance/jsx/file.tsx:22:38: 'yy' is declared here.
const d2 =
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentOverload5.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentOverload5.errors.txt
index fc177bee73b79..84db546e73c6c 100644
--- a/tests/baselines/reference/tsxStatelessFunctionComponentOverload5.errors.txt
+++ b/tests/baselines/reference/tsxStatelessFunctionComponentOverload5.errors.txt
@@ -22,13 +22,15 @@ tests/cases/conformance/jsx/file.tsx(55,68): error TS2769: No overload matches t
Type 'boolean' is not assignable to type 'string'.
Overload 3 of 3, '(hyphenProps: HyphenProps): Element', gave the following error.
Type 'boolean' is not assignable to type 'string'.
-tests/cases/conformance/jsx/file.tsx(56,12): error TS2769: No overload matches this call.
+tests/cases/conformance/jsx/file.tsx(56,13): error TS2769: No overload matches this call.
Overload 1 of 3, '(buttonProps: ButtonProps): Element', gave the following error.
Property 'onClick' is missing in type '{ "data-format": true; }' but required in type 'ButtonProps'.
Overload 2 of 3, '(linkProps: LinkProps): Element', gave the following error.
Property 'to' is missing in type '{ "data-format": true; }' but required in type 'LinkProps'.
Overload 3 of 3, '(hyphenProps: HyphenProps): Element', gave the following error.
- Type 'boolean' is not assignable to type 'string'.
+ Type '{ "data-format": true; }' is not assignable to type 'HyphenProps'.
+ Types of property '"data-format"' are incompatible.
+ Type 'boolean' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/file.tsx (4 errors) ====
@@ -122,14 +124,15 @@ tests/cases/conformance/jsx/file.tsx(56,12): error TS2769: No overload matches t
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:5:5: The expected type comes from property 'className' which is declared here on type 'IntrinsicAttributes & LinkProps'
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:5:5: The expected type comes from property 'className' which is declared here on type 'IntrinsicAttributes & HyphenProps'
const b8 = ; // incorrect type for specified hyphanated name
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~~~~~~~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 3, '(buttonProps: ButtonProps): Element', gave the following error.
!!! error TS2769: Property 'onClick' is missing in type '{ "data-format": true; }' but required in type 'ButtonProps'.
!!! error TS2769: Overload 2 of 3, '(linkProps: LinkProps): Element', gave the following error.
!!! error TS2769: Property 'to' is missing in type '{ "data-format": true; }' but required in type 'LinkProps'.
!!! error TS2769: Overload 3 of 3, '(hyphenProps: HyphenProps): Element', gave the following error.
-!!! error TS2769: Type 'boolean' is not assignable to type 'string'.
+!!! error TS2769: Type '{ "data-format": true; }' is not assignable to type 'HyphenProps'.
+!!! error TS2769: Types of property '"data-format"' are incompatible.
+!!! error TS2769: Type 'boolean' is not assignable to type 'string'.
!!! related TS2728 tests/cases/conformance/jsx/file.tsx:9:5: 'onClick' is declared here.
-!!! related TS2728 tests/cases/conformance/jsx/file.tsx:13:5: 'to' is declared here.
-!!! related TS6500 tests/cases/conformance/jsx/file.tsx:17:5: The expected type comes from property 'data-format' which is declared here on type 'IntrinsicAttributes & HyphenProps'
\ No newline at end of file
+!!! related TS2728 tests/cases/conformance/jsx/file.tsx:13:5: 'to' is declared here.
\ No newline at end of file
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt
index d31c2afc5607a..4f59b5a4e89c0 100644
--- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt
+++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt
@@ -1,4 +1,7 @@
-tests/cases/conformance/jsx/file.tsx(8,43): error TS2322: Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/jsx/file.tsx(8,15): error TS2322: Type 'T & { "ignore-prop": number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'.
+ Type 'T & { "ignore-prop": number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'.
+ Types of property '"ignore-prop"' are incompatible.
+ Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(13,15): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { prop: unknown; "ignore-prop": string; }'.
Type 'T' is not assignable to type '{ prop: unknown; "ignore-prop": string; }'.
tests/cases/conformance/jsx/file.tsx(20,19): error TS2322: Type '(a: number, b: string) => void' is not assignable to type '(arg: number) => void'.
@@ -16,9 +19,11 @@ tests/cases/conformance/jsx/file.tsx(31,52): error TS2322: Type '(val: string) =
// Error
function Bar(arg: T) {
let a1 = ;
- ~~~~~~~~~~~
-!!! error TS2322: Type 'number' is not assignable to type 'string'.
-!!! related TS6500 tests/cases/conformance/jsx/file.tsx:3:53: The expected type comes from property 'ignore-prop' which is declared here on type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'
+ ~~~~~~~~~~~~~~~~~~
+!!! error TS2322: Type 'T & { "ignore-prop": number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'.
+!!! error TS2322: Type 'T & { "ignore-prop": number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'.
+!!! error TS2322: Types of property '"ignore-prop"' are incompatible.
+!!! error TS2322: Type 'number' is not assignable to type 'string'.
}
// Error
diff --git a/tests/cases/compiler/ignoredJsxAttributes.tsx b/tests/cases/compiler/ignoredJsxAttributes.tsx
new file mode 100644
index 0000000000000..b4eb5337b1fb0
--- /dev/null
+++ b/tests/cases/compiler/ignoredJsxAttributes.tsx
@@ -0,0 +1,22 @@
+// @strict: true
+// @jsx: react
+///
+
+// Repro from #44797
+
+import * as React from "react";
+
+interface Props {
+ foo: string;
+ [dataProp: string]: string;
+}
+
+declare function Yadda(props: Props): JSX.Element;
+
+let props: Props = {
+ foo: "",
+ "data-yadda": 42, // Error
+};
+
+let x1 = ;
+let x2 = ; // Error