Skip to content

Commit ba77592

Browse files
committed
Merge pull request #4106 from RyanCavanaugh/allowTsxStringIndexers
Implements #4105 - a string indexer in 'props' disables errors due to surplus attributes
2 parents 085f0df + 5f96788 commit ba77592

File tree

4 files changed

+129
-4
lines changed

4 files changed

+129
-4
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7273,10 +7273,19 @@ namespace ts {
72737273
else if (elementAttributesType && !isTypeAny(elementAttributesType)) {
72747274
let correspondingPropSymbol = getPropertyOfType(elementAttributesType, node.name.text);
72757275
correspondingPropType = correspondingPropSymbol && getTypeOfSymbol(correspondingPropSymbol);
7276-
// If there's no corresponding property with this name, error
7277-
if (!correspondingPropType && isUnhyphenatedJsxName(node.name.text)) {
7278-
error(node.name, Diagnostics.Property_0_does_not_exist_on_type_1, node.name.text, typeToString(elementAttributesType));
7279-
return unknownType;
7276+
if (isUnhyphenatedJsxName(node.name.text)) {
7277+
// Maybe there's a string indexer?
7278+
let indexerType = getIndexTypeOfType(elementAttributesType, IndexKind.String);
7279+
if (indexerType) {
7280+
correspondingPropType = indexerType
7281+
}
7282+
else {
7283+
// If there's no corresponding property with this name, error
7284+
if (!correspondingPropType) {
7285+
error(node.name, Diagnostics.Property_0_does_not_exist_on_type_1, node.name.text, typeToString(elementAttributesType));
7286+
return unknownType;
7287+
}
7288+
}
72807289
}
72817290
}
72827291

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
tests/cases/conformance/jsx/file.tsx(11,14): error TS2322: Type 'string' is not assignable to type 'boolean'.
2+
3+
4+
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
5+
6+
declare module JSX {
7+
interface Element { }
8+
interface IntrinsicElements {
9+
}
10+
interface ElementAttributesProperty {
11+
props;
12+
}
13+
}
14+
15+
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
16+
export class MyComponent {
17+
render() {
18+
}
19+
20+
props: {
21+
[s: string]: boolean;
22+
}
23+
}
24+
25+
// Should be an error
26+
<MyComponent bar='world' />;
27+
~~~~~~~~~~~
28+
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
29+
30+
// Should be OK
31+
<MyComponent bar={true} />;
32+
33+
// Should be ok
34+
<MyComponent data-bar='hello' />;
35+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//// [tests/cases/conformance/jsx/tsxAttributeResolution10.tsx] ////
2+
3+
//// [react.d.ts]
4+
5+
declare module JSX {
6+
interface Element { }
7+
interface IntrinsicElements {
8+
}
9+
interface ElementAttributesProperty {
10+
props;
11+
}
12+
}
13+
14+
//// [file.tsx]
15+
export class MyComponent {
16+
render() {
17+
}
18+
19+
props: {
20+
[s: string]: boolean;
21+
}
22+
}
23+
24+
// Should be an error
25+
<MyComponent bar='world' />;
26+
27+
// Should be OK
28+
<MyComponent bar={true} />;
29+
30+
// Should be ok
31+
<MyComponent data-bar='hello' />;
32+
33+
34+
//// [file.jsx]
35+
define(["require", "exports"], function (require, exports) {
36+
var MyComponent = (function () {
37+
function MyComponent() {
38+
}
39+
MyComponent.prototype.render = function () {
40+
};
41+
return MyComponent;
42+
})();
43+
exports.MyComponent = MyComponent;
44+
// Should be an error
45+
<MyComponent bar='world'/>;
46+
// Should be OK
47+
<MyComponent bar={true}/>;
48+
// Should be ok
49+
<MyComponent data-bar='hello'/>;
50+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@jsx: preserve
2+
//@module: amd
3+
4+
//@filename: react.d.ts
5+
declare module JSX {
6+
interface Element { }
7+
interface IntrinsicElements {
8+
}
9+
interface ElementAttributesProperty {
10+
props;
11+
}
12+
}
13+
14+
//@filename: file.tsx
15+
export class MyComponent {
16+
render() {
17+
}
18+
19+
props: {
20+
[s: string]: boolean;
21+
}
22+
}
23+
24+
// Should be an error
25+
<MyComponent bar='world' />;
26+
27+
// Should be OK
28+
<MyComponent bar={true} />;
29+
30+
// Should be ok
31+
<MyComponent data-bar='hello' />;

0 commit comments

Comments
 (0)