Improve error message for invalid return type of JSX component (#32702)

* New diagnostic message for wrong JSX function component

* Component and Mixed type

* fix existing tests

* add new test for JSX component return type error

* fix tslint error

* update diagnostic message to include component name

* accept baseline

* update tests

* missing semicolon

* accept baseline

Co-authored-by: Wesley Wigham <wwigham@gmail.com>
This commit is contained in:
uhyo
2020-03-31 05:04:33 +09:00
committed by GitHub
parent 4c440e5e5b
commit 1f56ab02f0
12 changed files with 509 additions and 47 deletions

View File

@@ -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);
}
}

View File

@@ -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",