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 = ;