@@ -14766,80 +14766,69 @@ namespace ts {
14766
14766
signatures = mapDefined(signatures, s => getJsxSignatureTypeArgumentInstantiation(s, context, isJs));
14767
14767
}
14768
14768
14769
- return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromConstructSignature (t, isJs, context) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
14769
+ return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromClassType (t, isJs, context, /*reportErrors*/ false ) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
14770
14770
}
14771
14771
14772
14772
function getJsxPropsTypeFromCallSignature(sig: Signature, context: Node) {
14773
- let propsType = getTypeOfFirstParameterOfSignature (sig);
14773
+ let propsType = getTypeOfFirstParameterOfSignatureWithFallback (sig, emptyObjectType );
14774
14774
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
14775
14775
if (intrinsicAttribs !== unknownType) {
14776
14776
propsType = intersectTypes(intrinsicAttribs, propsType);
14777
14777
}
14778
14778
return propsType;
14779
14779
}
14780
14780
14781
- function getJsxPropsTypeFromClassType(hostClassType: Type, isJs: boolean, context: JsxOpeningLikeElement, reportErrors: boolean ) {
14782
- if (isTypeAny(hostClassType)) {
14783
- return hostClassType ;
14784
- }
14781
+ function getJsxPropsTypeForSignatureFromMember(sig: Signature, forcedLookupLocation: __String ) {
14782
+ const instanceType = getReturnTypeOfSignature(sig);
14783
+ return isTypeAny(instanceType) ? instanceType : getTypeOfPropertyOfType(instanceType, forcedLookupLocation) ;
14784
+ }
14785
14785
14786
- const propsName = getJsxElementPropertiesName(getJsxNamespaceAt(context));
14787
- if (propsName === undefined) {
14788
- // There is no type ElementAttributesProperty, return 'any'
14789
- return anyType;
14786
+ function getJsxPropsTypeFromClassType(sig: Signature, isJs: boolean, context: JsxOpeningLikeElement, reportErrors: boolean) {
14787
+ const forcedLookupLocation = getJsxElementPropertiesName(getJsxNamespaceAt(context));
14788
+ const attributesType = forcedLookupLocation === undefined
14789
+ // If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type
14790
+ ? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType)
14791
+ : forcedLookupLocation === ""
14792
+ // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
14793
+ ? getReturnTypeOfSignature(sig)
14794
+ // Otherwise get the type of the property on the signature return type
14795
+ : getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation);
14796
+
14797
+ if (!attributesType) {
14798
+ // There is no property named 'props' on this instance type
14799
+ if (reportErrors && !!forcedLookupLocation && !!length(context.attributes.properties)) {
14800
+ error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation));
14801
+ }
14802
+ return emptyObjectType;
14790
14803
}
14791
- else if (propsName === "" ) {
14792
- // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
14793
- return hostClassType ;
14804
+ else if (isTypeAny(attributesType) ) {
14805
+ // Props is of type 'any' or unknown
14806
+ return attributesType ;
14794
14807
}
14795
14808
else {
14796
- const attributesType = getTypeOfPropertyOfType(hostClassType, propsName);
14797
-
14798
- if (!attributesType) {
14799
- // There is no property named 'props' on this instance type
14800
- if (reportErrors && !!length(context.attributes.properties)) {
14801
- error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(propsName));
14802
- }
14803
- return emptyObjectType;
14809
+ // Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
14810
+ let apparentAttributesType = attributesType;
14811
+ const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context);
14812
+ if (intrinsicClassAttribs !== unknownType) {
14813
+ const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
14814
+ const hostClassType = getReturnTypeOfSignature(sig);
14815
+ apparentAttributesType = intersectTypes(
14816
+ typeParams
14817
+ ? createTypeReference(<GenericType>intrinsicClassAttribs, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isJs))
14818
+ : intrinsicClassAttribs,
14819
+ apparentAttributesType
14820
+ );
14804
14821
}
14805
- else if (isTypeAny(attributesType)) {
14806
- // Props is of type 'any' or unknown
14807
- return attributesType;
14808
- }
14809
- else {
14810
- // Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
14811
- let apparentAttributesType = attributesType;
14812
- const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context);
14813
- if (intrinsicClassAttribs !== unknownType) {
14814
- const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
14815
- apparentAttributesType = intersectTypes(
14816
- typeParams
14817
- ? createTypeReference(<GenericType>intrinsicClassAttribs, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isJs))
14818
- : intrinsicClassAttribs,
14819
- apparentAttributesType
14820
- );
14821
- }
14822
-
14823
- const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
14824
- if (intrinsicAttribs !== unknownType) {
14825
- apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
14826
- }
14827
14822
14828
- return apparentAttributesType;
14823
+ const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
14824
+ if (intrinsicAttribs !== unknownType) {
14825
+ apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
14829
14826
}
14830
- }
14831
- }
14832
14827
14833
- function getJsxPropsTypeFromConstructSignature(sig: Signature, isJs: boolean, context: JsxOpeningLikeElement) {
14834
- const hostClassType = getReturnTypeOfSignature(sig);
14835
- if (hostClassType) {
14836
- return getJsxPropsTypeFromClassType(hostClassType, isJs, context, /*reportErrors*/ false);
14828
+ return apparentAttributesType;
14837
14829
}
14838
- return getJsxPropsTypeFromCallSignature(sig, context);
14839
14830
}
14840
14831
14841
-
14842
-
14843
14832
// If the given type is an object or union type with a single signature, and if that signature has at
14844
14833
// least as many parameters as the given function, return the signature. Otherwise return undefined.
14845
14834
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
@@ -15556,31 +15545,7 @@ namespace ts {
15556
15545
return links.resolvedSymbol;
15557
15546
}
15558
15547
15559
- /**
15560
- * Given a JSX element that is a class element, finds the Element Instance Type. If the
15561
- * element is not a class element, or the class element type cannot be determined, returns 'undefined'.
15562
- * For example, in the element <MyClass>, the element instance type is `MyClass` (not `typeof MyClass`).
15563
- */
15564
- function getJsxElementInstanceType(node: JsxOpeningLikeElement, valueType: Type) {
15565
- Debug.assert(!(valueType.flags & TypeFlags.Union));
15566
- if (isTypeAny(valueType)) {
15567
- // Short-circuit if the class tag is using an element type 'any'
15568
- return anyType;
15569
- }
15570
-
15571
- // Resolve the signatures, preferring constructor
15572
- let signatures = getSignaturesOfType(valueType, SignatureKind.Construct);
15573
- if (signatures.length === 0) {
15574
- // No construct signatures, try call signatures
15575
- signatures = getSignaturesOfType(valueType, SignatureKind.Call);
15576
- if (signatures.length === 0) {
15577
- // We found no signatures at all, which is an error
15578
- error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName));
15579
- return unknownType;
15580
- }
15581
- }
15582
-
15583
- // Instantiate in context of source type
15548
+ function instantiateJsxSignatures(node: JsxOpeningLikeElement, signatures: Signature[]) {
15584
15549
const instantiatedSignatures = [];
15585
15550
let candidateForTypeArgumentError: Signature;
15586
15551
let hasTypeArgumentError: boolean = !!node.typeArguments;
@@ -15605,7 +15570,6 @@ namespace ts {
15605
15570
instantiatedSignatures.push(signature);
15606
15571
}
15607
15572
}
15608
-
15609
15573
if (node.typeArguments && hasTypeArgumentError) {
15610
15574
if (candidateForTypeArgumentError) {
15611
15575
checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true);
@@ -15615,8 +15579,7 @@ namespace ts {
15615
15579
diagnostics.add(getTypeArgumentArityError(node, signatures, node.typeArguments));
15616
15580
}
15617
15581
}
15618
-
15619
- return getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
15582
+ return instantiatedSignatures;
15620
15583
}
15621
15584
15622
15585
function getJsxSignatureTypeArgumentInstantiation(signature: Signature, node: JsxOpeningLikeElement, isJavascript: boolean, reportErrors?: boolean) {
@@ -15827,8 +15790,12 @@ namespace ts {
15827
15790
}), UnionReduction.Subtype);
15828
15791
}
15829
15792
15793
+ // Shortcircuit any
15794
+ if (isTypeAny(elementType)) {
15795
+ return elementType;
15796
+ }
15830
15797
// If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type
15831
- if (elementType.flags & TypeFlags.String) {
15798
+ else if (elementType.flags & TypeFlags.String) {
15832
15799
return anyType;
15833
15800
}
15834
15801
else if (elementType.flags & TypeFlags.StringLiteral) {
@@ -15854,7 +15821,22 @@ namespace ts {
15854
15821
}
15855
15822
15856
15823
// Get the element instance type (the result of newing or invoking this tag)
15857
- const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType);
15824
+
15825
+ // Resolve the signatures, preferring constructor
15826
+ let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
15827
+ if (signatures.length === 0) {
15828
+ // No construct signatures, try call signatures
15829
+ signatures = getSignaturesOfType(elementType, SignatureKind.Call);
15830
+ if (signatures.length === 0) {
15831
+ // We found no signatures at all, which is an error
15832
+ error(openingLikeElement.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(openingLikeElement.tagName));
15833
+ return unknownType;
15834
+ }
15835
+ }
15836
+
15837
+ // Instantiate in context of source type
15838
+ const instantiatedSignatures = instantiateJsxSignatures(openingLikeElement, signatures);
15839
+ const elemInstanceType = getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
15858
15840
15859
15841
// If we should include all stateless attributes type, then get all attributes type from all stateless function signature.
15860
15842
// Otherwise get only attributes type from the signature picked by choose-overload logic.
@@ -15871,7 +15853,8 @@ namespace ts {
15871
15853
checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
15872
15854
}
15873
15855
15874
- return getJsxPropsTypeFromClassType(elemInstanceType, isInJavaScriptFile(openingLikeElement), openingLikeElement, /*reportErrors*/ true);
15856
+ const isJs = isInJavaScriptFile(openingLikeElement);
15857
+ return getUnionType(map(instantiatedSignatures, sig => getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true)));
15875
15858
}
15876
15859
15877
15860
/**
@@ -18469,8 +18452,13 @@ namespace ts {
18469
18452
pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType;
18470
18453
}
18471
18454
18455
+
18472
18456
function getTypeOfFirstParameterOfSignature(signature: Signature) {
18473
- return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : neverType;
18457
+ return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType);
18458
+ }
18459
+
18460
+ function getTypeOfFirstParameterOfSignatureWithFallback(signature: Signature, fallbackType: Type) {
18461
+ return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : fallbackType;
18474
18462
}
18475
18463
18476
18464
function inferFromAnnotatedParameters(signature: Signature, context: Signature, mapper: TypeMapper) {
@@ -27565,7 +27553,7 @@ namespace ts {
27565
27553
export const JSX = "JSX" as __String;
27566
27554
export const IntrinsicElements = "IntrinsicElements" as __String;
27567
27555
export const ElementClass = "ElementClass" as __String;
27568
- export const ElementAttributesPropertyNameContainer = "ElementAttributesProperty" as __String;
27556
+ export const ElementAttributesPropertyNameContainer = "ElementAttributesProperty" as __String; // TODO: Deprecate and remove support
27569
27557
export const ElementChildrenAttributeNameContainer = "ElementChildrenAttribute" as __String;
27570
27558
export const Element = "Element" as __String;
27571
27559
export const IntrinsicAttributes = "IntrinsicAttributes" as __String;
0 commit comments