Skip to content

Commit 1344b14

Browse files
committed
Merge pull request microsoft#3771 from RyanCavanaugh/fix3737
Fix bug microsoft#3737 (exported JSX classes props not validated)
2 parents 8cdd59f + 3e57af1 commit 1344b14

File tree

6 files changed

+201
-11
lines changed

6 files changed

+201
-11
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7095,14 +7095,17 @@ namespace ts {
70957095

70967096
// Look up the value in the current scope
70977097
if (node.tagName.kind === SyntaxKind.Identifier) {
7098-
valueSymbol = getResolvedSymbol(<Identifier>node.tagName);
7098+
let tag = <Identifier>node.tagName;
7099+
let sym = getResolvedSymbol(tag);
7100+
valueSymbol = sym.exportSymbol || sym;
70997101
}
71007102
else {
71017103
valueSymbol = checkQualifiedName(<QualifiedName>node.tagName).symbol;
71027104
}
71037105

7104-
if (valueSymbol !== unknownSymbol) {
7106+
if (valueSymbol && valueSymbol !== unknownSymbol) {
71057107
links.jsxFlags |= JsxFlags.ClassElement;
7108+
getSymbolLinks(valueSymbol).referenced = true;
71067109
}
71077110

71087111
return valueSymbol || unknownSymbol;
@@ -7311,15 +7314,6 @@ namespace ts {
73117314

73127315
let targetAttributesType = getJsxElementAttributesType(node);
73137316

7314-
if (getNodeLinks(node).jsxFlags & JsxFlags.ClassElement) {
7315-
if (node.tagName.kind === SyntaxKind.Identifier) {
7316-
checkIdentifier(<Identifier>node.tagName);
7317-
}
7318-
else {
7319-
checkQualifiedName(<QualifiedName>node.tagName);
7320-
}
7321-
}
7322-
73237317
let nameTable: Map<boolean> = {};
73247318
// Process this array in right-to-left order so we know which
73257319
// attributes (mostly from spreads) are being overwritten and
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
tests/cases/conformance/jsx/file.tsx(9,14): error TS2322: Type 'number' is not assignable to type 'string'.
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+
interface Props {
16+
foo: string;
17+
}
18+
19+
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
20+
export class MyComponent {
21+
render() {
22+
}
23+
24+
props: { foo: string; }
25+
}
26+
27+
<MyComponent foo="bar" />; // ok
28+
<MyComponent foo={0} />; // should be an error
29+
~~~~~~~
30+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
31+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [tests/cases/conformance/jsx/tsxAttributeResolution9.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+
interface Props {
15+
foo: string;
16+
}
17+
18+
//// [file.tsx]
19+
export class MyComponent {
20+
render() {
21+
}
22+
23+
props: { foo: string; }
24+
}
25+
26+
<MyComponent foo="bar" />; // ok
27+
<MyComponent foo={0} />; // should be an error
28+
29+
30+
//// [file.jsx]
31+
define(["require", "exports"], function (require, exports) {
32+
var MyComponent = (function () {
33+
function MyComponent() {
34+
}
35+
MyComponent.prototype.render = function () {
36+
};
37+
return MyComponent;
38+
})();
39+
exports.MyComponent = MyComponent;
40+
<MyComponent foo="bar"/>; // ok
41+
<MyComponent foo={0}/>; // should be an error
42+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
=== tests/cases/conformance/jsx/react.d.ts ===
2+
3+
declare module JSX {
4+
>JSX : Symbol(JSX, Decl(react.d.ts, 0, 0))
5+
6+
interface Element { }
7+
>Element : Symbol(Element, Decl(react.d.ts, 1, 20))
8+
9+
interface IntrinsicElements {
10+
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react.d.ts, 2, 22))
11+
}
12+
interface ElementAttributesProperty {
13+
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(react.d.ts, 4, 2))
14+
15+
props;
16+
>props : Symbol(props, Decl(react.d.ts, 5, 38))
17+
}
18+
}
19+
20+
interface Props {
21+
>Props : Symbol(Props, Decl(react.d.ts, 8, 1))
22+
23+
foo: string;
24+
>foo : Symbol(foo, Decl(react.d.ts, 10, 17))
25+
}
26+
27+
=== tests/cases/conformance/jsx/file.tsx ===
28+
export class MyComponent {
29+
>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0))
30+
31+
render() {
32+
>render : Symbol(render, Decl(file.tsx, 0, 26))
33+
}
34+
35+
props: { foo: string; }
36+
>props : Symbol(props, Decl(file.tsx, 2, 3))
37+
>foo : Symbol(foo, Decl(file.tsx, 4, 10))
38+
}
39+
40+
<MyComponent foo="bar" />; // ok
41+
>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0))
42+
>foo : Symbol(unknown)
43+
44+
<MyComponent foo={0} />; // should be an error
45+
>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0))
46+
>foo : Symbol(unknown)
47+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
=== tests/cases/conformance/jsx/react.d.ts ===
2+
3+
declare module JSX {
4+
>JSX : any
5+
6+
interface Element { }
7+
>Element : Element
8+
9+
interface IntrinsicElements {
10+
>IntrinsicElements : IntrinsicElements
11+
}
12+
interface ElementAttributesProperty {
13+
>ElementAttributesProperty : ElementAttributesProperty
14+
15+
props;
16+
>props : any
17+
}
18+
}
19+
20+
interface Props {
21+
>Props : Props
22+
23+
foo: string;
24+
>foo : string
25+
}
26+
27+
=== tests/cases/conformance/jsx/file.tsx ===
28+
export class MyComponent {
29+
>MyComponent : MyComponent
30+
31+
render() {
32+
>render : () => void
33+
}
34+
35+
props: { foo: string; }
36+
>props : { foo: string; }
37+
>foo : string
38+
}
39+
40+
<MyComponent foo="bar" />; // ok
41+
><MyComponent foo="bar" /> : JSX.Element
42+
>MyComponent : typeof MyComponent
43+
>foo : any
44+
45+
<MyComponent foo={0} />; // should be an error
46+
><MyComponent foo={0} /> : JSX.Element
47+
>MyComponent : typeof MyComponent
48+
>foo : any
49+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
interface Props {
15+
foo: string;
16+
}
17+
18+
//@filename: file.tsx
19+
export class MyComponent {
20+
render() {
21+
}
22+
23+
props: { foo: string; }
24+
}
25+
26+
<MyComponent foo="bar" />; // ok
27+
<MyComponent foo={0} />; // should be an error

0 commit comments

Comments
 (0)