@@ -6567,7 +6567,7 @@ namespace ts {
6567
6567
6568
6568
function findMatchingSignature(signatureList: ReadonlyArray<Signature>, signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined {
6569
6569
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)) {
6571
6571
return s;
6572
6572
}
6573
6573
}
@@ -6603,8 +6603,7 @@ namespace ts {
6603
6603
// Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional
6604
6604
// parameters and may differ in return types. When signatures differ in return types, the resulting return
6605
6605
// 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[] {
6608
6607
let result: Signature[] | undefined;
6609
6608
for (let i = 0; i < signatureLists.length; i++) {
6610
6609
for (const signature of signatureLists[i]) {
@@ -6650,8 +6649,8 @@ namespace ts {
6650
6649
function resolveUnionTypeMembers(type: UnionType) {
6651
6650
// The members and properties collections are empty for union types. To get all properties of a union
6652
6651
// 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)) );
6655
6654
const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String);
6656
6655
const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number);
6657
6656
setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
@@ -10691,6 +10690,10 @@ namespace ts {
10691
10690
return isTypeRelatedTo(source, target, assignableRelation) ? Ternary.True : Ternary.False;
10692
10691
}
10693
10692
10693
+ function compareTypesSubtypeOf(source: Type, target: Type): Ternary {
10694
+ return isTypeRelatedTo(source, target, subtypeRelation) ? Ternary.True : Ternary.False;
10695
+ }
10696
+
10694
10697
function isTypeSubtypeOf(source: Type, target: Type): boolean {
10695
10698
return isTypeRelatedTo(source, target, subtypeRelation);
10696
10699
}
@@ -12880,7 +12883,7 @@ namespace ts {
12880
12883
for (let i = 0; i < targetLen; i++) {
12881
12884
const s = getTypeAtPosition(source, i);
12882
12885
const t = getTypeAtPosition(target, i);
12883
- const related = compareTypes(s, t );
12886
+ const related = compareTypes(t, s );
12884
12887
if (!related) {
12885
12888
return Ternary.False;
12886
12889
}
@@ -17108,7 +17111,7 @@ namespace ts {
17108
17111
}
17109
17112
17110
17113
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);
17112
17115
}
17113
17116
17114
17117
function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
@@ -18004,13 +18007,17 @@ namespace ts {
18004
18007
return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace);
18005
18008
}
18006
18009
18007
- function getUninstantiatedJsxSignaturesOfType(elementType: Type) {
18010
+ function getUninstantiatedJsxSignaturesOfType(elementType: Type): ReadonlyArray<Signature> {
18008
18011
// Resolve the signatures, preferring constructor
18009
18012
let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
18010
18013
if (signatures.length === 0) {
18011
18014
// No construct signatures, try call signatures
18012
18015
signatures = getSignaturesOfType(elementType, SignatureKind.Call);
18013
18016
}
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
+ }
18014
18021
return signatures;
18015
18022
}
18016
18023
@@ -18036,20 +18043,29 @@ namespace ts {
18036
18043
return anyType;
18037
18044
}
18038
18045
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 ) {
18041
18048
const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
18042
18049
if (sfcReturnConstraint) {
18043
18050
checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
18044
18051
}
18045
18052
}
18046
- else {
18053
+ else if (refKind === JsxReferenceKind.Component) {
18047
18054
const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
18048
18055
if (classConstraint) {
18049
18056
// Issue an error if this return type isn't assignable to JSX.ElementClass or JSX.Element, failing that
18050
18057
checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
18051
18058
}
18052
18059
}
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
+ }
18053
18069
}
18054
18070
18055
18071
/**
@@ -18139,7 +18155,7 @@ namespace ts {
18139
18155
18140
18156
if (isNodeOpeningLikeElement) {
18141
18157
const sig = getResolvedSignature(node as JsxOpeningLikeElement);
18142
- checkJsxReturnAssignableToAppropriateBound(isJsxStatelessFunctionReference (node as JsxOpeningLikeElement), getReturnTypeOfSignature(sig), node);
18158
+ checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind (node as JsxOpeningLikeElement), getReturnTypeOfSignature(sig), node);
18143
18159
}
18144
18160
}
18145
18161
@@ -19174,12 +19190,18 @@ namespace ts {
19174
19190
return typeArgumentTypes;
19175
19191
}
19176
19192
19177
- function isJsxStatelessFunctionReference (node: JsxOpeningLikeElement) {
19193
+ function getJsxReferenceKind (node: JsxOpeningLikeElement): JsxReferenceKind {
19178
19194
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;
19180
19203
}
19181
- const tagType = checkExpression(node.tagName);
19182
- return !length(getSignaturesOfType(getApparentType(tagType), SignatureKind.Construct));
19204
+ return JsxReferenceKind.Mixed;
19183
19205
}
19184
19206
19185
19207
/**
@@ -20182,13 +20204,11 @@ namespace ts {
20182
20204
}
20183
20205
}
20184
20206
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)) {
20188
20209
return resolveUntypedCall(node);
20189
20210
}
20190
20211
20191
- const signatures = getUninstantiatedJsxSignaturesOfType(apparentType);
20192
20212
if (signatures.length === 0) {
20193
20213
// We found no signatures at all, which is an error
20194
20214
error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName));
0 commit comments