diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 2f7332c181e02..6182dfe42ca35 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -23356,18 +23356,18 @@ namespace ts {
return anyType;
}
- function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind, elemInstanceType: Type, openingLikeElement: Node) {
+ function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind, elemInstanceType: Type, openingLikeElement: JsxOpeningLikeElement) {
if (refKind === JsxReferenceKind.Function) {
const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
if (sfcReturnConstraint) {
- checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
+ checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
}
}
else if (refKind === JsxReferenceKind.Component) {
const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
if (classConstraint) {
- // Issue an error if this return type isn't assignable to JSX.ElementClass or JSX.Element, failing that
- checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
+ // Issue an error if this return type isn't assignable to JSX.ElementClass, failing that
+ checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
}
}
else { // Mixed
@@ -23377,7 +23377,12 @@ namespace ts {
return;
}
const combined = getUnionType([sfcReturnConstraint, classConstraint]);
- checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
+ checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
+ }
+
+ function generateInitialErrorChain(): DiagnosticMessageChain {
+ const componentName = getTextOfNode(openingLikeElement.tagName);
+ return chainDiagnosticMessages(/* details */ undefined, Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName);
}
}
@@ -23468,8 +23473,9 @@ namespace ts {
}
if (isNodeOpeningLikeElement) {
- const sig = getResolvedSignature(node as JsxOpeningLikeElement);
- checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(node as JsxOpeningLikeElement), getReturnTypeOfSignature(sig), node);
+ const jsxOpeningLikeNode = node as JsxOpeningLikeElement;
+ const sig = getResolvedSignature(jsxOpeningLikeNode);
+ checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(jsxOpeningLikeNode), getReturnTypeOfSignature(sig), jsxOpeningLikeNode);
}
}
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index db517cbe52d76..992b1595bf746 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -2947,6 +2947,22 @@
"category": "Error",
"code": 2785
},
+ "'{0}' cannot be used as a JSX component.": {
+ "category": "Error",
+ "code": 2786
+ },
+ "Its return type '{0}' is not a valid JSX element.": {
+ "category": "Error",
+ "code": 2787
+ },
+ "Its instance type '{0}' is not a valid JSX element.": {
+ "category": "Error",
+ "code": 2788
+ },
+ "Its element type '{0}' is not a valid JSX element.": {
+ "category": "Error",
+ "code": 2789
+ },
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
diff --git a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt
index b62c3592ef6a8..a2d542ffb69dd 100644
--- a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt
+++ b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt
@@ -1,11 +1,14 @@
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
-tests/cases/conformance/jsx/inline/index.tsx(21,21): error TS2605: JSX element type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not a constructor function for JSX elements.
- Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
+tests/cases/conformance/jsx/inline/index.tsx(21,22): error TS2786: 'MySFC' cannot be used as a JSX component.
+ Its return type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not a valid JSX element.
+ Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
-tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
- Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
+tests/cases/conformance/jsx/inline/index.tsx(21,41): error TS2786: 'MyClass' cannot be used as a JSX component.
+ Its instance type 'MyClass' is not a valid JSX element.
+ Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
-tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
+tests/cases/conformance/jsx/inline/index.tsx(21,64): error TS2786: 'MyClass' cannot be used as a JSX component.
+ Its instance type 'MyClass' is not a valid JSX element.
tests/cases/conformance/jsx/inline/index.tsx(24,42): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
@@ -95,20 +98,23 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
// Should fail, no dom elements
const _brokenTree =
- ~~~~~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not a constructor function for JSX elements.
-!!! error TS2605: Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
+ ~~~~~
+!!! error TS2786: 'MySFC' cannot be used as a JSX component.
+!!! error TS2786: Its return type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not a valid JSX element.
+!!! error TS2786: Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer.d.ts:7:13: '__domBrand' is declared here.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
- ~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
-!!! error TS2605: Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
+ ~~~~~~~
+!!! error TS2786: 'MyClass' cannot be used as a JSX component.
+!!! error TS2786: Its instance type 'MyClass' is not a valid JSX element.
+!!! error TS2786: Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer.d.ts:7:13: '__domBrand' is declared here.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
- ~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
+ ~~~~~~~
+!!! error TS2786: 'MyClass' cannot be used as a JSX component.
+!!! error TS2786: Its instance type 'MyClass' is not a valid JSX element.
// Should fail, nondom isn't allowed as children of dom
const _brokenTree2 = {tree}{tree}
diff --git a/tests/baselines/reference/jsxComponentTypeErrors.errors.txt b/tests/baselines/reference/jsxComponentTypeErrors.errors.txt
new file mode 100644
index 0000000000000..9f25590c593ad
--- /dev/null
+++ b/tests/baselines/reference/jsxComponentTypeErrors.errors.txt
@@ -0,0 +1,103 @@
+tests/cases/compiler/jsxComponentTypeErrors.tsx(16,11): error TS2786: 'this' cannot be used as a JSX component.
+ Its return type '{ type: "foo" | undefined; }' is not a valid JSX element.
+ Types of property 'type' are incompatible.
+ Type '"foo" | undefined' is not assignable to type '"element"'.
+ Type 'undefined' is not assignable to type '"element"'.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(25,16): error TS2786: 'FunctionComponent' cannot be used as a JSX component.
+ Its return type '{ type: "abc" | undefined; }' is not a valid JSX element.
+ Types of property 'type' are incompatible.
+ Type '"abc" | undefined' is not assignable to type '"element"'.
+ Type 'undefined' is not assignable to type '"element"'.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(26,16): error TS2786: 'FunctionComponent' cannot be used as a JSX component.
+ Its return type '{ type: "abc" | undefined; }' is not a valid JSX element.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(27,16): error TS2786: 'ClassComponent' cannot be used as a JSX component.
+ Its instance type 'ClassComponent' is not a valid JSX element.
+ Types of property 'type' are incompatible.
+ Type 'string' is not assignable to type '"element-class"'.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(28,16): error TS2786: 'MixedComponent' cannot be used as a JSX component.
+ Its element type 'ClassComponent | { type: string | undefined; }' is not a valid JSX element.
+ Type 'ClassComponent' is not assignable to type 'Element | ElementClass | null'.
+ Type 'ClassComponent' is not assignable to type 'ElementClass'.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(37,16): error TS2786: 'obj.MemberFunctionComponent' cannot be used as a JSX component.
+ Its return type '{}' is not a valid JSX element.
+ Property 'type' is missing in type '{}' but required in type 'Element'.
+tests/cases/compiler/jsxComponentTypeErrors.tsx(38,16): error TS2786: 'obj. MemberClassComponent' cannot be used as a JSX component.
+ Its instance type 'MemberClassComponent' is not a valid JSX element.
+ Property 'type' is missing in type 'MemberClassComponent' but required in type 'ElementClass'.
+
+
+==== tests/cases/compiler/jsxComponentTypeErrors.tsx (7 errors) ====
+ namespace JSX {
+ export interface Element {
+ type: 'element';
+ }
+ export interface ElementClass {
+ type: 'element-class';
+ }
+ }
+
+ function FunctionComponent({type}: {type?: T}) {
+ return {
+ type
+ }
+ }
+ FunctionComponent.useThis = function() {
+ return ;
+ ~~~~
+!!! error TS2786: 'this' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{ type: "foo" | undefined; }' is not a valid JSX element.
+!!! error TS2786: Types of property 'type' are incompatible.
+!!! error TS2786: Type '"foo" | undefined' is not assignable to type '"element"'.
+!!! error TS2786: Type 'undefined' is not assignable to type '"element"'.
+ }
+
+ class ClassComponent {
+ type = 'string';
+ }
+
+ const MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+
+ const elem1 = ;
+ ~~~~~~~~~~~~~~~~~
+!!! error TS2786: 'FunctionComponent' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{ type: "abc" | undefined; }' is not a valid JSX element.
+!!! error TS2786: Types of property 'type' are incompatible.
+!!! error TS2786: Type '"abc" | undefined' is not assignable to type '"element"'.
+!!! error TS2786: Type 'undefined' is not assignable to type '"element"'.
+ const elem2 = />;
+ ~~~~~~~~~~~~~~~~~
+!!! error TS2786: 'FunctionComponent' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{ type: "abc" | undefined; }' is not a valid JSX element.
+ const elem3 = ;
+ ~~~~~~~~~~~~~~
+!!! error TS2786: 'ClassComponent' cannot be used as a JSX component.
+!!! error TS2786: Its instance type 'ClassComponent' is not a valid JSX element.
+!!! error TS2786: Types of property 'type' are incompatible.
+!!! error TS2786: Type 'string' is not assignable to type '"element-class"'.
+ const elem4 = ;
+ ~~~~~~~~~~~~~~
+!!! error TS2786: 'MixedComponent' cannot be used as a JSX component.
+!!! error TS2786: Its element type 'ClassComponent | { type: string | undefined; }' is not a valid JSX element.
+!!! error TS2786: Type 'ClassComponent' is not assignable to type 'Element | ElementClass | null'.
+!!! error TS2786: Type 'ClassComponent' is not assignable to type 'ElementClass'.
+
+ const obj = {
+ MemberFunctionComponent() {
+ return {};
+ },
+ MemberClassComponent: class {},
+ };
+
+ const elem5 = ;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2786: 'obj.MemberFunctionComponent' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{}' is not a valid JSX element.
+!!! error TS2786: Property 'type' is missing in type '{}' but required in type 'Element'.
+!!! related TS2728 tests/cases/compiler/jsxComponentTypeErrors.tsx:3:5: 'type' is declared here.
+ const elem6 = ;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2786: 'obj. MemberClassComponent' cannot be used as a JSX component.
+!!! error TS2786: Its instance type 'MemberClassComponent' is not a valid JSX element.
+!!! error TS2786: Property 'type' is missing in type 'MemberClassComponent' but required in type 'ElementClass'.
+!!! related TS2728 tests/cases/compiler/jsxComponentTypeErrors.tsx:6:5: 'type' is declared here.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxComponentTypeErrors.js b/tests/baselines/reference/jsxComponentTypeErrors.js
new file mode 100644
index 0000000000000..9787531cf0808
--- /dev/null
+++ b/tests/baselines/reference/jsxComponentTypeErrors.js
@@ -0,0 +1,75 @@
+//// [jsxComponentTypeErrors.tsx]
+namespace JSX {
+ export interface Element {
+ type: 'element';
+ }
+ export interface ElementClass {
+ type: 'element-class';
+ }
+}
+
+function FunctionComponent({type}: {type?: T}) {
+ return {
+ type
+ }
+}
+FunctionComponent.useThis = function() {
+ return ;
+}
+
+class ClassComponent {
+ type = 'string';
+}
+
+const MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+
+const elem1 = ;
+const elem2 = />;
+const elem3 = ;
+const elem4 = ;
+
+const obj = {
+ MemberFunctionComponent() {
+ return {};
+ },
+ MemberClassComponent: class {},
+};
+
+const elem5 = ;
+const elem6 = ;
+
+
+//// [jsxComponentTypeErrors.jsx]
+"use strict";
+function FunctionComponent(_a) {
+ var type = _a.type;
+ return {
+ type: type
+ };
+}
+FunctionComponent.useThis = function () {
+ return ;
+};
+var ClassComponent = /** @class */ (function () {
+ function ClassComponent() {
+ this.type = 'string';
+ }
+ return ClassComponent;
+}());
+var MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+var elem1 = ;
+var elem2 = ;
+var elem3 = ;
+var elem4 = ;
+var obj = {
+ MemberFunctionComponent: function () {
+ return {};
+ },
+ MemberClassComponent: /** @class */ (function () {
+ function MemberClassComponent() {
+ }
+ return MemberClassComponent;
+ }())
+};
+var elem5 = ;
+var elem6 = ;
diff --git a/tests/baselines/reference/jsxComponentTypeErrors.symbols b/tests/baselines/reference/jsxComponentTypeErrors.symbols
new file mode 100644
index 0000000000000..f728d5a5f0404
--- /dev/null
+++ b/tests/baselines/reference/jsxComponentTypeErrors.symbols
@@ -0,0 +1,97 @@
+=== tests/cases/compiler/jsxComponentTypeErrors.tsx ===
+namespace JSX {
+>JSX : Symbol(JSX, Decl(jsxComponentTypeErrors.tsx, 0, 0))
+
+ export interface Element {
+>Element : Symbol(Element, Decl(jsxComponentTypeErrors.tsx, 0, 15))
+
+ type: 'element';
+>type : Symbol(Element.type, Decl(jsxComponentTypeErrors.tsx, 1, 28))
+ }
+ export interface ElementClass {
+>ElementClass : Symbol(ElementClass, Decl(jsxComponentTypeErrors.tsx, 3, 3))
+
+ type: 'element-class';
+>type : Symbol(ElementClass.type, Decl(jsxComponentTypeErrors.tsx, 4, 33))
+ }
+}
+
+function FunctionComponent({type}: {type?: T}) {
+>FunctionComponent : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>T : Symbol(T, Decl(jsxComponentTypeErrors.tsx, 9, 27))
+>type : Symbol(type, Decl(jsxComponentTypeErrors.tsx, 9, 46))
+>type : Symbol(type, Decl(jsxComponentTypeErrors.tsx, 9, 54))
+>T : Symbol(T, Decl(jsxComponentTypeErrors.tsx, 9, 27))
+
+ return {
+ type
+>type : Symbol(type, Decl(jsxComponentTypeErrors.tsx, 10, 10))
+ }
+}
+FunctionComponent.useThis = function() {
+>FunctionComponent.useThis : Symbol(FunctionComponent.useThis, Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>FunctionComponent : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>useThis : Symbol(FunctionComponent.useThis, Decl(jsxComponentTypeErrors.tsx, 13, 1))
+
+ return ;
+>this : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>type : Symbol(type, Decl(jsxComponentTypeErrors.tsx, 15, 14))
+}
+
+class ClassComponent {
+>ClassComponent : Symbol(ClassComponent, Decl(jsxComponentTypeErrors.tsx, 16, 1))
+
+ type = 'string';
+>type : Symbol(ClassComponent.type, Decl(jsxComponentTypeErrors.tsx, 18, 22))
+}
+
+const MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+>MixedComponent : Symbol(MixedComponent, Decl(jsxComponentTypeErrors.tsx, 22, 5))
+>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
+>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
+>FunctionComponent : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>ClassComponent : Symbol(ClassComponent, Decl(jsxComponentTypeErrors.tsx, 16, 1))
+
+const elem1 = ;
+>elem1 : Symbol(elem1, Decl(jsxComponentTypeErrors.tsx, 24, 5))
+>FunctionComponent : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+>type : Symbol(type, Decl(jsxComponentTypeErrors.tsx, 24, 32))
+
+const elem2 = />;
+>elem2 : Symbol(elem2, Decl(jsxComponentTypeErrors.tsx, 25, 5))
+>FunctionComponent : Symbol(FunctionComponent, Decl(jsxComponentTypeErrors.tsx, 7, 1), Decl(jsxComponentTypeErrors.tsx, 13, 1))
+
+const elem3 = ;
+>elem3 : Symbol(elem3, Decl(jsxComponentTypeErrors.tsx, 26, 5))
+>ClassComponent : Symbol(ClassComponent, Decl(jsxComponentTypeErrors.tsx, 16, 1))
+
+const elem4 = ;
+>elem4 : Symbol(elem4, Decl(jsxComponentTypeErrors.tsx, 27, 5))
+>MixedComponent : Symbol(MixedComponent, Decl(jsxComponentTypeErrors.tsx, 22, 5))
+
+const obj = {
+>obj : Symbol(obj, Decl(jsxComponentTypeErrors.tsx, 29, 5))
+
+ MemberFunctionComponent() {
+>MemberFunctionComponent : Symbol(MemberFunctionComponent, Decl(jsxComponentTypeErrors.tsx, 29, 13))
+
+ return {};
+ },
+ MemberClassComponent: class {},
+>MemberClassComponent : Symbol(MemberClassComponent, Decl(jsxComponentTypeErrors.tsx, 32, 4))
+
+};
+
+const elem5 = ;
+>elem5 : Symbol(elem5, Decl(jsxComponentTypeErrors.tsx, 36, 5))
+>obj.MemberFunctionComponent : Symbol(MemberFunctionComponent, Decl(jsxComponentTypeErrors.tsx, 29, 13))
+>obj : Symbol(obj, Decl(jsxComponentTypeErrors.tsx, 29, 5))
+>MemberFunctionComponent : Symbol(MemberFunctionComponent, Decl(jsxComponentTypeErrors.tsx, 29, 13))
+
+const elem6 = ;
+>elem6 : Symbol(elem6, Decl(jsxComponentTypeErrors.tsx, 37, 5))
+>obj. MemberClassComponent : Symbol(MemberClassComponent, Decl(jsxComponentTypeErrors.tsx, 32, 4))
+>obj : Symbol(obj, Decl(jsxComponentTypeErrors.tsx, 29, 5))
+>MemberClassComponent : Symbol(MemberClassComponent, Decl(jsxComponentTypeErrors.tsx, 32, 4))
+
diff --git a/tests/baselines/reference/jsxComponentTypeErrors.types b/tests/baselines/reference/jsxComponentTypeErrors.types
new file mode 100644
index 0000000000000..39b1c661eb228
--- /dev/null
+++ b/tests/baselines/reference/jsxComponentTypeErrors.types
@@ -0,0 +1,107 @@
+=== tests/cases/compiler/jsxComponentTypeErrors.tsx ===
+namespace JSX {
+ export interface Element {
+ type: 'element';
+>type : "element"
+ }
+ export interface ElementClass {
+ type: 'element-class';
+>type : "element-class"
+ }
+}
+
+function FunctionComponent({type}: {type?: T}) {
+>FunctionComponent : typeof FunctionComponent
+>type : T | undefined
+>type : T | undefined
+
+ return {
+>{ type } : { type: T | undefined; }
+
+ type
+>type : T | undefined
+ }
+}
+FunctionComponent.useThis = function() {
+>FunctionComponent.useThis = function() { return ;} : () => JSX.Element
+>FunctionComponent.useThis : () => JSX.Element
+>FunctionComponent : typeof FunctionComponent
+>useThis : () => JSX.Element
+>function() { return ;} : () => JSX.Element
+
+ return ;
+> : JSX.Element
+>this : typeof FunctionComponent
+>type : "foo"
+}
+
+class ClassComponent {
+>ClassComponent : ClassComponent
+
+ type = 'string';
+>type : string
+>'string' : "string"
+}
+
+const MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+>MixedComponent : typeof FunctionComponent | typeof ClassComponent
+>Math.random() ? FunctionComponent : ClassComponent : typeof FunctionComponent | typeof ClassComponent
+>Math.random() : number
+>Math.random : () => number
+>Math : Math
+>random : () => number
+>FunctionComponent : typeof FunctionComponent
+>ClassComponent : typeof ClassComponent
+
+const elem1 = ;
+>elem1 : JSX.Element
+> : JSX.Element
+>FunctionComponent : typeof FunctionComponent
+>type : "abc"
+
+const elem2 = />;
+>elem2 : JSX.Element
+> /> : JSX.Element
+>FunctionComponent : typeof FunctionComponent
+
+const elem3 = ;
+>elem3 : JSX.Element
+> : JSX.Element
+>ClassComponent : typeof ClassComponent
+
+const elem4 = ;
+>elem4 : JSX.Element
+> : JSX.Element
+>MixedComponent : typeof FunctionComponent | typeof ClassComponent
+
+const obj = {
+>obj : { MemberFunctionComponent(): {}; MemberClassComponent: typeof MemberClassComponent; }
+>{ MemberFunctionComponent() { return {}; }, MemberClassComponent: class {},} : { MemberFunctionComponent(): {}; MemberClassComponent: typeof MemberClassComponent; }
+
+ MemberFunctionComponent() {
+>MemberFunctionComponent : () => {}
+
+ return {};
+>{} : {}
+
+ },
+ MemberClassComponent: class {},
+>MemberClassComponent : typeof MemberClassComponent
+>class {} : typeof MemberClassComponent
+
+};
+
+const elem5 = ;
+>elem5 : JSX.Element
+> : JSX.Element
+>obj.MemberFunctionComponent : () => {}
+>obj : { MemberFunctionComponent(): {}; MemberClassComponent: typeof MemberClassComponent; }
+>MemberFunctionComponent : () => {}
+
+const elem6 = ;
+>elem6 : JSX.Element
+> : JSX.Element
+>obj. MemberClassComponent : typeof MemberClassComponent
+>obj : { MemberFunctionComponent(): {}; MemberClassComponent: typeof MemberClassComponent; }
+>MemberClassComponent : typeof MemberClassComponent
+
diff --git a/tests/baselines/reference/tsxElementResolution10.errors.txt b/tests/baselines/reference/tsxElementResolution10.errors.txt
index 3a2802c2ac053..a3c557f462c7c 100644
--- a/tests/baselines/reference/tsxElementResolution10.errors.txt
+++ b/tests/baselines/reference/tsxElementResolution10.errors.txt
@@ -1,6 +1,7 @@
-tests/cases/conformance/jsx/file.tsx(13,1): error TS2605: JSX element type '{ x: number; }' is not a constructor function for JSX elements.
- Property 'render' is missing in type '{ x: number; }' but required in type 'ElementClass'.
tests/cases/conformance/jsx/file.tsx(13,2): error TS2322: Type '{ x: number; }' is not assignable to type 'string'.
+tests/cases/conformance/jsx/file.tsx(13,2): error TS2786: 'Obj1' cannot be used as a JSX component.
+ Its instance type '{ x: number; }' is not a valid JSX element.
+ Property 'render' is missing in type '{ x: number; }' but required in type 'ElementClass'.
tests/cases/conformance/jsx/file.tsx(19,2): error TS2322: Type '{ x: number; render: number; }' is not assignable to type 'string'.
@@ -18,12 +19,13 @@ tests/cases/conformance/jsx/file.tsx(19,2): error TS2322: Type '{ x: number; ren
}
var Obj1: Obj1type;
; // Error, no render member
- ~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type '{ x: number; }' is not a constructor function for JSX elements.
-!!! error TS2605: Property 'render' is missing in type '{ x: number; }' but required in type 'ElementClass'.
-!!! related TS2728 tests/cases/conformance/jsx/file.tsx:4:3: 'render' is declared here.
~~~~
!!! error TS2322: Type '{ x: number; }' is not assignable to type 'string'.
+ ~~~~
+!!! error TS2786: 'Obj1' cannot be used as a JSX component.
+!!! error TS2786: Its instance type '{ x: number; }' is not a valid JSX element.
+!!! error TS2786: Property 'render' is missing in type '{ x: number; }' but required in type 'ElementClass'.
+!!! related TS2728 tests/cases/conformance/jsx/file.tsx:4:3: 'render' is declared here.
interface Obj2type {
(n: string): { x: number; render: any; };
diff --git a/tests/baselines/reference/tsxElementResolution9.errors.txt b/tests/baselines/reference/tsxElementResolution9.errors.txt
index 38d4c941335f6..31d0fa5d1a645 100644
--- a/tests/baselines/reference/tsxElementResolution9.errors.txt
+++ b/tests/baselines/reference/tsxElementResolution9.errors.txt
@@ -3,20 +3,22 @@ tests/cases/conformance/jsx/file.tsx(11,2): error TS2769: No overload matches th
Type '{}' is not assignable to type 'string'.
Overload 2 of 2, '(n: number): { y: string; }', gave the following error.
Type '{}' is not assignable to type 'number'.
-tests/cases/conformance/jsx/file.tsx(18,1): error TS2605: JSX element type '{ x: number; } & { y: string; }' is not a constructor function for JSX elements.
- Property 'something' is missing in type '{ x: number; } & { y: string; }' but required in type 'Element'.
tests/cases/conformance/jsx/file.tsx(18,2): error TS2769: No overload matches this call.
Overload 1 of 2, '(n: string): { x: number; }', gave the following error.
Type '{}' is not assignable to type 'string'.
Overload 2 of 2, '(n: number): { y: string; }', gave the following error.
Type '{}' is not assignable to type 'number'.
-tests/cases/conformance/jsx/file.tsx(25,1): error TS2605: JSX element type '{ x: number; } & { x: number; y: string; }' is not a constructor function for JSX elements.
- Property 'something' is missing in type '{ x: number; } & { x: number; y: string; }' but required in type 'Element'.
+tests/cases/conformance/jsx/file.tsx(18,2): error TS2786: 'Obj2' cannot be used as a JSX component.
+ Its return type '{ x: number; } & { y: string; }' is not a valid JSX element.
+ Property 'something' is missing in type '{ x: number; } & { y: string; }' but required in type 'Element'.
tests/cases/conformance/jsx/file.tsx(25,2): error TS2769: No overload matches this call.
Overload 1 of 2, '(n: string): { x: number; }', gave the following error.
Type '{ x: number; }' is not assignable to type 'string'.
Overload 2 of 2, '(n: number): { x: number; y: string; }', gave the following error.
Type '{ x: number; }' is not assignable to type 'number'.
+tests/cases/conformance/jsx/file.tsx(25,2): error TS2786: 'Obj3' cannot be used as a JSX component.
+ Its return type '{ x: number; } & { x: number; y: string; }' is not a valid JSX element.
+ Property 'something' is missing in type '{ x: number; } & { x: number; y: string; }' but required in type 'Element'.
==== tests/cases/conformance/jsx/file.tsx (5 errors) ====
@@ -44,16 +46,17 @@ tests/cases/conformance/jsx/file.tsx(25,2): error TS2769: No overload matches th
}
var Obj2: Obj2;
; // Error, return type is not an object type
- ~~~~~~~~
-!!! error TS2605: JSX element type '{ x: number; } & { y: string; }' is not a constructor function for JSX elements.
-!!! error TS2605: Property 'something' is missing in type '{ x: number; } & { y: string; }' but required in type 'Element'.
-!!! related TS2728 tests/cases/conformance/jsx/file.tsx:2:22: 'something' is declared here.
~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(n: string): { x: number; }', gave the following error.
!!! error TS2769: Type '{}' is not assignable to type 'string'.
!!! error TS2769: Overload 2 of 2, '(n: number): { y: string; }', gave the following error.
!!! error TS2769: Type '{}' is not assignable to type 'number'.
+ ~~~~
+!!! error TS2786: 'Obj2' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{ x: number; } & { y: string; }' is not a valid JSX element.
+!!! error TS2786: Property 'something' is missing in type '{ x: number; } & { y: string; }' but required in type 'Element'.
+!!! related TS2728 tests/cases/conformance/jsx/file.tsx:2:22: 'something' is declared here.
interface Obj3 {
(n: string): { x: number };
@@ -61,14 +64,15 @@ tests/cases/conformance/jsx/file.tsx(25,2): error TS2769: No overload matches th
}
var Obj3: Obj3;
; // OK
- ~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type '{ x: number; } & { x: number; y: string; }' is not a constructor function for JSX elements.
-!!! error TS2605: Property 'something' is missing in type '{ x: number; } & { x: number; y: string; }' but required in type 'Element'.
-!!! related TS2728 tests/cases/conformance/jsx/file.tsx:2:22: 'something' is declared here.
~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(n: string): { x: number; }', gave the following error.
!!! error TS2769: Type '{ x: number; }' is not assignable to type 'string'.
!!! error TS2769: Overload 2 of 2, '(n: number): { x: number; y: string; }', gave the following error.
!!! error TS2769: Type '{ x: number; }' is not assignable to type 'number'.
+ ~~~~
+!!! error TS2786: 'Obj3' cannot be used as a JSX component.
+!!! error TS2786: Its return type '{ x: number; } & { x: number; y: string; }' is not a valid JSX element.
+!!! error TS2786: Property 'something' is missing in type '{ x: number; } & { x: number; y: string; }' but required in type 'Element'.
+!!! related TS2728 tests/cases/conformance/jsx/file.tsx:2:22: 'something' is declared here.
\ No newline at end of file
diff --git a/tests/baselines/reference/tsxSfcReturnUndefinedStrictNullChecks.errors.txt b/tests/baselines/reference/tsxSfcReturnUndefinedStrictNullChecks.errors.txt
index f3452f62ccba9..dd9698624e540 100644
--- a/tests/baselines/reference/tsxSfcReturnUndefinedStrictNullChecks.errors.txt
+++ b/tests/baselines/reference/tsxSfcReturnUndefinedStrictNullChecks.errors.txt
@@ -1,5 +1,7 @@
-tests/cases/conformance/jsx/file.tsx(9,13): error TS2605: JSX element type 'undefined' is not a constructor function for JSX elements.
-tests/cases/conformance/jsx/file.tsx(10,11): error TS2605: JSX element type 'undefined' is not a constructor function for JSX elements.
+tests/cases/conformance/jsx/file.tsx(9,14): error TS2786: 'Foo' cannot be used as a JSX component.
+ Its return type 'undefined' is not a valid JSX element.
+tests/cases/conformance/jsx/file.tsx(10,12): error TS2786: 'Greet' cannot be used as a JSX component.
+ Its return type 'undefined' is not a valid JSX element.
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
@@ -12,8 +14,10 @@ tests/cases/conformance/jsx/file.tsx(10,11): error TS2605: JSX element type 'und
// Error
const foo = ;
- ~~~~~~~
-!!! error TS2605: JSX element type 'undefined' is not a constructor function for JSX elements.
+ ~~~
+!!! error TS2786: 'Foo' cannot be used as a JSX component.
+!!! error TS2786: Its return type 'undefined' is not a valid JSX element.
const G = ;
- ~~~~~~~~~
-!!! error TS2605: JSX element type 'undefined' is not a constructor function for JSX elements.
\ No newline at end of file
+ ~~~~~
+!!! error TS2786: 'Greet' cannot be used as a JSX component.
+!!! error TS2786: Its return type 'undefined' is not a valid JSX element.
\ No newline at end of file
diff --git a/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt b/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt
index 25d62a07fa514..c084b175c0b3b 100644
--- a/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt
+++ b/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt
@@ -1,4 +1,5 @@
-tests/cases/compiler/file.tsx(11,1): error TS2605: JSX element type 'string' is not a constructor function for JSX elements.
+tests/cases/compiler/file.tsx(11,2): error TS2786: 'SFC' cannot be used as a JSX component.
+ Its return type 'string' is not a valid JSX element.
tests/cases/compiler/file.tsx(11,14): error TS2322: Type 'number' is not assignable to type 'string'.
@@ -14,8 +15,9 @@ tests/cases/compiler/file.tsx(11,14): error TS2322: Type 'number' is not assigna
}
prop={1}>; // should error
- ~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2605: JSX element type 'string' is not a constructor function for JSX elements.
+ ~~~
+!!! error TS2786: 'SFC' cannot be used as a JSX component.
+!!! error TS2786: Its return type 'string' is not a valid JSX element.
~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
\ No newline at end of file
diff --git a/tests/cases/compiler/jsxComponentTypeErrors.tsx b/tests/cases/compiler/jsxComponentTypeErrors.tsx
new file mode 100644
index 0000000000000..b04196ae020b9
--- /dev/null
+++ b/tests/cases/compiler/jsxComponentTypeErrors.tsx
@@ -0,0 +1,40 @@
+// @strict: true
+// @jsx: preserve
+namespace JSX {
+ export interface Element {
+ type: 'element';
+ }
+ export interface ElementClass {
+ type: 'element-class';
+ }
+}
+
+function FunctionComponent({type}: {type?: T}) {
+ return {
+ type
+ }
+}
+FunctionComponent.useThis = function() {
+ return ;
+}
+
+class ClassComponent {
+ type = 'string';
+}
+
+const MixedComponent = Math.random() ? FunctionComponent : ClassComponent;
+
+const elem1 = ;
+const elem2 = />;
+const elem3 = ;
+const elem4 = ;
+
+const obj = {
+ MemberFunctionComponent() {
+ return {};
+ },
+ MemberClassComponent: class {},
+};
+
+const elem5 = ;
+const elem6 = ;