diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b59bd2df2b..1edd2a7a920 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7095,14 +7095,17 @@ namespace ts { // Look up the value in the current scope if (node.tagName.kind === SyntaxKind.Identifier) { - valueSymbol = getResolvedSymbol(node.tagName); + let tag = node.tagName; + let sym = getResolvedSymbol(tag); + valueSymbol = sym.exportSymbol || sym; } else { valueSymbol = checkQualifiedName(node.tagName).symbol; } - if (valueSymbol !== unknownSymbol) { + if (valueSymbol && valueSymbol !== unknownSymbol) { links.jsxFlags |= JsxFlags.ClassElement; + getSymbolLinks(valueSymbol).referenced = true; } return valueSymbol || unknownSymbol; @@ -7311,15 +7314,6 @@ namespace ts { let targetAttributesType = getJsxElementAttributesType(node); - if (getNodeLinks(node).jsxFlags & JsxFlags.ClassElement) { - if (node.tagName.kind === SyntaxKind.Identifier) { - checkIdentifier(node.tagName); - } - else { - checkQualifiedName(node.tagName); - } - } - let nameTable: Map = {}; // Process this array in right-to-left order so we know which // attributes (mostly from spreads) are being overwritten and diff --git a/tests/baselines/reference/tsxAttributeResolution9.errors.txt b/tests/baselines/reference/tsxAttributeResolution9.errors.txt new file mode 100644 index 00000000000..c25532eaa0a --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution9.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/jsx/file.tsx(9,14): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/jsx/react.d.ts (0 errors) ==== + + declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + } + + interface Props { + foo: string; + } + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + export class MyComponent { + render() { + } + + props: { foo: string; } + } + + ; // ok + ; // should be an error + ~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributeResolution9.js b/tests/baselines/reference/tsxAttributeResolution9.js new file mode 100644 index 00000000000..bfc19a7ba4f --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution9.js @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/jsx/tsxAttributeResolution9.tsx] //// + +//// [react.d.ts] + +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } +} + +interface Props { + foo: string; +} + +//// [file.tsx] +export class MyComponent { + render() { + } + + props: { foo: string; } +} + +; // ok +; // should be an error + + +//// [file.jsx] +define(["require", "exports"], function (require, exports) { + var MyComponent = (function () { + function MyComponent() { + } + MyComponent.prototype.render = function () { + }; + return MyComponent; + })(); + exports.MyComponent = MyComponent; + ; // ok + ; // should be an error +}); diff --git a/tests/baselines/reference/tsxAttributeResolution9.symbols b/tests/baselines/reference/tsxAttributeResolution9.symbols new file mode 100644 index 00000000000..081482d5d47 --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution9.symbols @@ -0,0 +1,47 @@ +=== tests/cases/conformance/jsx/react.d.ts === + +declare module JSX { +>JSX : Symbol(JSX, Decl(react.d.ts, 0, 0)) + + interface Element { } +>Element : Symbol(Element, Decl(react.d.ts, 1, 20)) + + interface IntrinsicElements { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(react.d.ts, 2, 22)) + } + interface ElementAttributesProperty { +>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(react.d.ts, 4, 2)) + + props; +>props : Symbol(props, Decl(react.d.ts, 5, 38)) + } +} + +interface Props { +>Props : Symbol(Props, Decl(react.d.ts, 8, 1)) + + foo: string; +>foo : Symbol(foo, Decl(react.d.ts, 10, 17)) +} + +=== tests/cases/conformance/jsx/file.tsx === +export class MyComponent { +>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0)) + + render() { +>render : Symbol(render, Decl(file.tsx, 0, 26)) + } + + props: { foo: string; } +>props : Symbol(props, Decl(file.tsx, 2, 3)) +>foo : Symbol(foo, Decl(file.tsx, 4, 10)) +} + +; // ok +>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0)) +>foo : Symbol(unknown) + +; // should be an error +>MyComponent : Symbol(MyComponent, Decl(file.tsx, 0, 0)) +>foo : Symbol(unknown) + diff --git a/tests/baselines/reference/tsxAttributeResolution9.types b/tests/baselines/reference/tsxAttributeResolution9.types new file mode 100644 index 00000000000..1b2c6d42389 --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution9.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/jsx/react.d.ts === + +declare module JSX { +>JSX : any + + interface Element { } +>Element : Element + + interface IntrinsicElements { +>IntrinsicElements : IntrinsicElements + } + interface ElementAttributesProperty { +>ElementAttributesProperty : ElementAttributesProperty + + props; +>props : any + } +} + +interface Props { +>Props : Props + + foo: string; +>foo : string +} + +=== tests/cases/conformance/jsx/file.tsx === +export class MyComponent { +>MyComponent : MyComponent + + render() { +>render : () => void + } + + props: { foo: string; } +>props : { foo: string; } +>foo : string +} + +; // ok +> : JSX.Element +>MyComponent : typeof MyComponent +>foo : any + +; // should be an error +> : JSX.Element +>MyComponent : typeof MyComponent +>foo : any + diff --git a/tests/cases/conformance/jsx/tsxAttributeResolution9.tsx b/tests/cases/conformance/jsx/tsxAttributeResolution9.tsx new file mode 100644 index 00000000000..9768d65d000 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxAttributeResolution9.tsx @@ -0,0 +1,27 @@ +//@jsx: preserve +//@module: amd + +//@filename: react.d.ts +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } +} + +interface Props { + foo: string; +} + +//@filename: file.tsx +export class MyComponent { + render() { + } + + props: { foo: string; } +} + +; // ok +; // should be an error