diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index fb4af5d7298..a5b96c4a9a8 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -8248,27 +8248,31 @@ namespace ts {
// Get the element instance type (the result of newing or invoking this tag)
const elemInstanceType = getJsxElementInstanceType(node);
- // Is this is a stateless function component? See if its single signature is
- // assignable to the JSX Element Type
- const callSignature = getSingleCallSignature(getTypeOfSymbol(sym));
- const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
- let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
- if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType) && (paramType.flags & TypeFlags.ObjectType)) {
- // Intersect in JSX.IntrinsicAttributes if it exists
- const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
- if (intrinsicAttributes !== unknownType) {
- paramType = intersectTypes(intrinsicAttributes, paramType);
+ const elemClassType = getJsxGlobalElementClassType();
+
+ if (!elemClassType || !isTypeAssignableTo(elemInstanceType, elemClassType)) {
+ // Is this is a stateless function component? See if its single signature's return type is
+ // assignable to the JSX Element Type
+ const elemType = getTypeOfSymbol(sym);
+ const callSignatures = elemType && getSignaturesOfType(elemType, SignatureKind.Call);
+ const callSignature = callSignatures && callSignatures.length > 0 && callSignatures[0];
+ const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
+ let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
+ if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
+ // Intersect in JSX.IntrinsicAttributes if it exists
+ const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
+ if (intrinsicAttributes !== unknownType) {
+ paramType = intersectTypes(intrinsicAttributes, paramType);
+ }
+ return paramType;
}
- return paramType;
}
// Issue an error if this return type isn't assignable to JSX.ElementClass
- const elemClassType = getJsxGlobalElementClassType();
if (elemClassType) {
checkTypeRelatedTo(elemInstanceType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
}
-
if (isTypeAny(elemInstanceType)) {
return links.resolvedJsxType = elemInstanceType;
}
diff --git a/tests/baselines/reference/tsxElementResolution9.js b/tests/baselines/reference/tsxElementResolution9.js
index bc65bb0bb02..5ad47730e4a 100644
--- a/tests/baselines/reference/tsxElementResolution9.js
+++ b/tests/baselines/reference/tsxElementResolution9.js
@@ -1,6 +1,6 @@
//// [file.tsx]
declare module JSX {
- interface Element { }
+ interface Element { something; }
interface IntrinsicElements { }
}
diff --git a/tests/baselines/reference/tsxElementResolution9.symbols b/tests/baselines/reference/tsxElementResolution9.symbols
index e38c64d0847..0aec19a8094 100644
--- a/tests/baselines/reference/tsxElementResolution9.symbols
+++ b/tests/baselines/reference/tsxElementResolution9.symbols
@@ -2,11 +2,12 @@
declare module JSX {
>JSX : Symbol(JSX, Decl(file.tsx, 0, 0))
- interface Element { }
+ interface Element { something; }
>Element : Symbol(Element, Decl(file.tsx, 0, 20))
+>something : Symbol(something, Decl(file.tsx, 1, 20))
interface IntrinsicElements { }
->IntrinsicElements : Symbol(IntrinsicElements, Decl(file.tsx, 1, 22))
+>IntrinsicElements : Symbol(IntrinsicElements, Decl(file.tsx, 1, 33))
}
interface Obj1 {
diff --git a/tests/baselines/reference/tsxElementResolution9.types b/tests/baselines/reference/tsxElementResolution9.types
index dd84e6f07b5..b138aa0509e 100644
--- a/tests/baselines/reference/tsxElementResolution9.types
+++ b/tests/baselines/reference/tsxElementResolution9.types
@@ -2,8 +2,9 @@
declare module JSX {
>JSX : any
- interface Element { }
+ interface Element { something; }
>Element : Element
+>something : any
interface IntrinsicElements { }
>IntrinsicElements : IntrinsicElements
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.js b/tests/baselines/reference/tsxStatelessFunctionComponents3.js
new file mode 100644
index 00000000000..d58586dd1ee
--- /dev/null
+++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.js
@@ -0,0 +1,37 @@
+//// [file.tsx]
+
+import React = require('react');
+
+const Foo = (props: any) =>
;
+// Should be OK
+const foo = ;
+
+
+// Should be OK
+var MainMenu: React.StatelessComponent<{}> = (props) => (
+
Main Menu
+);
+
+var App: React.StatelessComponent<{ children }> = ({children}) => (
+
+
+
+);
+
+//// [file.jsx]
+define(["require", "exports", 'react'], function (require, exports, React) {
+ "use strict";
+ var Foo = function (props) { return ; };
+ // Should be OK
+ var foo = ;
+ // Should be OK
+ var MainMenu = function (props) { return (
+
Main Menu
+); };
+ var App = function (_a) {
+ var children = _a.children;
+ return (
+
+
);
+ };
+});
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols
new file mode 100644
index 00000000000..4ce502c6a6a
--- /dev/null
+++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols
@@ -0,0 +1,48 @@
+=== tests/cases/conformance/jsx/file.tsx ===
+
+import React = require('react');
+>React : Symbol(React, Decl(file.tsx, 0, 0))
+
+const Foo = (props: any) => ;
+>Foo : Symbol(Foo, Decl(file.tsx, 3, 5))
+>props : Symbol(props, Decl(file.tsx, 3, 13))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 927, 45))
+
+// Should be OK
+const foo = ;
+>foo : Symbol(foo, Decl(file.tsx, 5, 5))
+>Foo : Symbol(Foo, Decl(file.tsx, 3, 5))
+
+
+// Should be OK
+var MainMenu: React.StatelessComponent<{}> = (props) => (
+>MainMenu : Symbol(MainMenu, Decl(file.tsx, 9, 3))
+>React : Symbol(React, Decl(file.tsx, 0, 0))
+>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 139, 5))
+>props : Symbol(props, Decl(file.tsx, 9, 46))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 927, 45))
+
+
Main Menu
+>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 939, 48))
+>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 939, 48))
+
+);
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 927, 45))
+
+var App: React.StatelessComponent<{ children }> = ({children}) => (
+>App : Symbol(App, Decl(file.tsx, 13, 3))
+>React : Symbol(React, Decl(file.tsx, 0, 0))
+>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 139, 5))
+>children : Symbol(children, Decl(file.tsx, 13, 35))
+>children : Symbol(children, Decl(file.tsx, 13, 52))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 927, 45))
+
+
+>MainMenu : Symbol(MainMenu, Decl(file.tsx, 9, 3))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 927, 45))
+
+);
diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.types b/tests/baselines/reference/tsxStatelessFunctionComponents3.types
new file mode 100644
index 00000000000..6531ff737ba
--- /dev/null
+++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.types
@@ -0,0 +1,59 @@
+=== tests/cases/conformance/jsx/file.tsx ===
+
+import React = require('react');
+>React : typeof React
+
+const Foo = (props: any) => ;
+>Foo : (props: any) => JSX.Element
+>(props: any) => : (props: any) => JSX.Element
+>props : any
+> : JSX.Element
+>div : any
+
+// Should be OK
+const foo = ;
+>foo : JSX.Element
+> : JSX.Element
+>Foo : (props: any) => JSX.Element
+
+
+// Should be OK
+var MainMenu: React.StatelessComponent<{}> = (props) => (
+>MainMenu : React.StatelessComponent<{}>
+>React : any
+>StatelessComponent : React.StatelessComponent
+>(props) => (
Main Menu
) : (props: {}) => JSX.Element
+>props : {}
+>(
Main Menu
) : JSX.Element
+>
Main Menu
: JSX.Element
+>div : any
+
+
Main Menu
+>
Main Menu
: JSX.Element
+>h3 : any
+>h3 : any
+
+
);
+>div : any
+
+var App: React.StatelessComponent<{ children }> = ({children}) => (
+>App : React.StatelessComponent<{ children: any; }>
+>React : any
+>StatelessComponent : React.StatelessComponent
+>children : any
+>({children}) => (
) : ({children}: { children: any; }) => JSX.Element
+>children : any
+>(
) : JSX.Element
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>MainMenu : React.StatelessComponent<{}>
+
+
+>div : any
+
+);
diff --git a/tests/cases/conformance/jsx/tsxElementResolution9.tsx b/tests/cases/conformance/jsx/tsxElementResolution9.tsx
index 7165f8277b3..4854484a225 100644
--- a/tests/cases/conformance/jsx/tsxElementResolution9.tsx
+++ b/tests/cases/conformance/jsx/tsxElementResolution9.tsx
@@ -1,7 +1,7 @@
//@filename: file.tsx
//@jsx: preserve
declare module JSX {
- interface Element { }
+ interface Element { something; }
interface IntrinsicElements { }
}
diff --git a/tests/cases/conformance/jsx/tsxStatelessFunctionComponents3.tsx b/tests/cases/conformance/jsx/tsxStatelessFunctionComponents3.tsx
new file mode 100644
index 00000000000..48ce5fb5efb
--- /dev/null
+++ b/tests/cases/conformance/jsx/tsxStatelessFunctionComponents3.tsx
@@ -0,0 +1,23 @@
+// @filename: file.tsx
+// @jsx: preserve
+// @module: amd
+// @noLib: true
+// @libFiles: react.d.ts,lib.d.ts
+
+import React = require('react');
+
+const Foo = (props: any) => ;
+// Should be OK
+const foo = ;
+
+
+// Should be OK
+var MainMenu: React.StatelessComponent<{}> = (props) => (
+
Main Menu
+);
+
+var App: React.StatelessComponent<{ children }> = ({children}) => (
+
+
+
+);
\ No newline at end of file