@@ -6567,7 +6567,7 @@ namespace ts {
65676567
65686568 function findMatchingSignature(signatureList: ReadonlyArray<Signature>, signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined {
65696569 for (const s of signatureList) {
6570- if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypesIdentical)) {
6570+ if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, partialMatch ? compareTypesSubtypeOf : compareTypesIdentical)) {
65716571 return s;
65726572 }
65736573 }
@@ -6603,8 +6603,7 @@ namespace ts {
66036603 // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional
66046604 // parameters and may differ in return types. When signatures differ in return types, the resulting return
66056605 // type is the union of the constituent return types.
6606- function getUnionSignatures(types: ReadonlyArray<Type>, kind: SignatureKind): Signature[] {
6607- const signatureLists = map(types, t => getSignaturesOfType(t, kind));
6606+ function getUnionSignatures(signatureLists: ReadonlyArray<ReadonlyArray<Signature>>): Signature[] {
66086607 let result: Signature[] | undefined;
66096608 for (let i = 0; i < signatureLists.length; i++) {
66106609 for (const signature of signatureLists[i]) {
@@ -6650,8 +6649,8 @@ namespace ts {
66506649 function resolveUnionTypeMembers(type: UnionType) {
66516650 // The members and properties collections are empty for union types. To get all properties of a union
66526651 // type use getPropertiesOfType (only the language service uses this).
6653- const callSignatures = getUnionSignatures(type.types, SignatureKind.Call);
6654- const constructSignatures = getUnionSignatures(type.types, SignatureKind.Construct);
6652+ const callSignatures = getUnionSignatures(map( type.types, t => getSignaturesOfType(t, SignatureKind.Call)) );
6653+ const constructSignatures = getUnionSignatures(map( type.types, t => getSignaturesOfType(t, SignatureKind.Construct)) );
66556654 const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String);
66566655 const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number);
66576656 setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
@@ -10691,6 +10690,10 @@ namespace ts {
1069110690 return isTypeRelatedTo(source, target, assignableRelation) ? Ternary.True : Ternary.False;
1069210691 }
1069310692
10693+ function compareTypesSubtypeOf(source: Type, target: Type): Ternary {
10694+ return isTypeRelatedTo(source, target, subtypeRelation) ? Ternary.True : Ternary.False;
10695+ }
10696+
1069410697 function isTypeSubtypeOf(source: Type, target: Type): boolean {
1069510698 return isTypeRelatedTo(source, target, subtypeRelation);
1069610699 }
@@ -12880,7 +12883,7 @@ namespace ts {
1288012883 for (let i = 0; i < targetLen; i++) {
1288112884 const s = getTypeAtPosition(source, i);
1288212885 const t = getTypeAtPosition(target, i);
12883- const related = compareTypes(s, t );
12886+ const related = compareTypes(t, s );
1288412887 if (!related) {
1288512888 return Ternary.False;
1288612889 }
@@ -17108,7 +17111,7 @@ namespace ts {
1710817111 }
1710917112
1711017113 function getEffectiveFirstArgumentForJsxSignature(signature: Signature, node: JsxOpeningLikeElement) {
17111- return isJsxStatelessFunctionReference (node) ? getJsxPropsTypeFromCallSignature(signature, node) : getJsxPropsTypeFromClassType(signature, node);
17114+ return getJsxReferenceKind (node) !== JsxReferenceKind.Component ? getJsxPropsTypeFromCallSignature(signature, node) : getJsxPropsTypeFromClassType(signature, node);
1711217115 }
1711317116
1711417117 function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
@@ -18004,13 +18007,17 @@ namespace ts {
1800418007 return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace);
1800518008 }
1800618009
18007- function getUninstantiatedJsxSignaturesOfType(elementType: Type) {
18010+ function getUninstantiatedJsxSignaturesOfType(elementType: Type): ReadonlyArray<Signature> {
1800818011 // Resolve the signatures, preferring constructor
1800918012 let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
1801018013 if (signatures.length === 0) {
1801118014 // No construct signatures, try call signatures
1801218015 signatures = getSignaturesOfType(elementType, SignatureKind.Call);
1801318016 }
18017+ if (signatures.length === 0 && elementType.flags & TypeFlags.Union) {
18018+ // If each member has some combination of new/call signatures; make a union signature list for those
18019+ signatures = getUnionSignatures(map((elementType as UnionType).types, getUninstantiatedJsxSignaturesOfType));
18020+ }
1801418021 return signatures;
1801518022 }
1801618023
@@ -18036,20 +18043,29 @@ namespace ts {
1803618043 return anyType;
1803718044 }
1803818045
18039- function checkJsxReturnAssignableToAppropriateBound(isSFC: boolean , elemInstanceType: Type, openingLikeElement: Node) {
18040- if (isSFC ) {
18046+ function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind , elemInstanceType: Type, openingLikeElement: Node) {
18047+ if (refKind === JsxReferenceKind.Function ) {
1804118048 const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
1804218049 if (sfcReturnConstraint) {
1804318050 checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
1804418051 }
1804518052 }
18046- else {
18053+ else if (refKind === JsxReferenceKind.Component) {
1804718054 const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
1804818055 if (classConstraint) {
1804918056 // Issue an error if this return type isn't assignable to JSX.ElementClass or JSX.Element, failing that
1805018057 checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
1805118058 }
1805218059 }
18060+ else { // Mixed
18061+ const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
18062+ const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
18063+ if (!sfcReturnConstraint || !classConstraint) {
18064+ return;
18065+ }
18066+ const combined = getUnionType([sfcReturnConstraint, classConstraint]);
18067+ checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
18068+ }
1805318069 }
1805418070
1805518071 /**
@@ -18139,7 +18155,7 @@ namespace ts {
1813918155
1814018156 if (isNodeOpeningLikeElement) {
1814118157 const sig = getResolvedSignature(node as JsxOpeningLikeElement);
18142- checkJsxReturnAssignableToAppropriateBound(isJsxStatelessFunctionReference (node as JsxOpeningLikeElement), getReturnTypeOfSignature(sig), node);
18158+ checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind (node as JsxOpeningLikeElement), getReturnTypeOfSignature(sig), node);
1814318159 }
1814418160 }
1814518161
@@ -19174,12 +19190,18 @@ namespace ts {
1917419190 return typeArgumentTypes;
1917519191 }
1917619192
19177- function isJsxStatelessFunctionReference (node: JsxOpeningLikeElement) {
19193+ function getJsxReferenceKind (node: JsxOpeningLikeElement): JsxReferenceKind {
1917819194 if (isJsxIntrinsicIdentifier(node.tagName)) {
19179- return true;
19195+ return JsxReferenceKind.Mixed;
19196+ }
19197+ const tagType = getApparentType(checkExpression(node.tagName));
19198+ if (length(getSignaturesOfType(tagType, SignatureKind.Construct))) {
19199+ return JsxReferenceKind.Component;
19200+ }
19201+ if (length(getSignaturesOfType(tagType, SignatureKind.Call))) {
19202+ return JsxReferenceKind.Function;
1918019203 }
19181- const tagType = checkExpression(node.tagName);
19182- return !length(getSignaturesOfType(getApparentType(tagType), SignatureKind.Construct));
19204+ return JsxReferenceKind.Mixed;
1918319205 }
1918419206
1918519207 /**
@@ -20182,13 +20204,11 @@ namespace ts {
2018220204 }
2018320205 }
2018420206
20185- const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
20186- const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
20187- if (exprTypes.flags & TypeFlags.String || isUntypedFunctionCall(exprTypes, apparentType, callSignatures.length, constructSignatures.length)) {
20207+ const signatures = getUninstantiatedJsxSignaturesOfType(apparentType);
20208+ if (exprTypes.flags & TypeFlags.String || isUntypedFunctionCall(exprTypes, apparentType, signatures.length, /*constructSignatures*/ 0)) {
2018820209 return resolveUntypedCall(node);
2018920210 }
2019020211
20191- const signatures = getUninstantiatedJsxSignaturesOfType(apparentType);
2019220212 if (signatures.length === 0) {
2019320213 // We found no signatures at all, which is an error
2019420214 error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName));
0 commit comments