@@ -11870,7 +11870,7 @@ namespace ts {
1187011870 * @param openingLikeElement a Jsx opening-like element
1187111871 * @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property.
1187211872 */
11873- function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?:(symbol: Symbol)=> boolean) {
11873+ function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean) {
1187411874 const attributes = openingLikeElement.attributes;
1187511875 let attributesTable = createMap<Symbol>();
1187611876 let spread: Type = emptyObjectType;
@@ -11924,8 +11924,8 @@ namespace ts {
1192411924 attributesTable = createMap<Symbol>();
1192511925 if (attributesArray) {
1192611926 forEach(attributesArray, (attr) => {
11927- if (!filter || ( filter && filter (attr) )) {
11928- attributesTable[ attr.name] = attr;
11927+ if (!filter || filter(attr)) {
11928+ attributesTable.set( attr.name, attr) ;
1192911929 }
1193011930 });
1193111931 }
@@ -11963,7 +11963,7 @@ namespace ts {
1196311963 */
1196411964 function checkJsxAttributesAssignableToTagnameAttributes(openingLikeElement: JsxOpeningLikeElement) {
1196511965 // The function involves following steps:
11966- // 1. Figure out expected attributes type expected by resolving tag-name of the JSX opening-like element, tagetAttributesType .
11966+ // 1. Figure out expected attributes type expected by resolving tag-name of the JSX opening-like element, targetAttributesType .
1196711967 // During these steps, we will try to resolve the tag-name as intrinsic name, stateless function, stateful component (in the order)
1196811968 // 2. Solved Jsx attributes type given by users, sourceAttributesType, which is by resolving "attributes" property of the JSX opening-like element.
1196911969 // 3. Check if the two are assignable to each other
@@ -11977,7 +11977,7 @@ namespace ts {
1197711977 // i.e <div attr1={10} attr2="string" />
1197811978 // attr1 and attr2 are treated as JSXAttributes attached in the JsxOpeningLikeElement as "attributes". They resolved to be sourceAttributesType.
1197911979 const sourceAttributesType = createJsxAttributesTypeFromAttributesProperty(openingLikeElement,
11980- ( attribute: Symbol) => {
11980+ attribute => {
1198111981 return isUnhyphenatedJsxName(attribute.name) || !!(getPropertyOfType(targetAttributesType, attribute.name));
1198211982 });
1198311983
@@ -13109,12 +13109,6 @@ namespace ts {
1310913109 * @param excludeArgument
1311013110 */
1311113111 function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>) {
13112- const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
13113- // Stateless function components can have maximum of three arguments: "props", "context", and "updater".
13114- // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
13115- // can be specified by users through attributes property.
13116- const paramType = getTypeAtPosition(signature, 0);
13117-
1311813112 // JSX opening-like element has correct arity for stateless-function component if the one of the following condition is true:
1311913113 // 1. callIsIncomplete
1312013114 // 2. attributes property has same number of properties as the parameter object type.
@@ -13126,6 +13120,11 @@ namespace ts {
1312613120 return true;
1312713121 }
1312813122
13123+ const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
13124+ // Stateless function components can have maximum of three arguments: "props", "context", and "updater".
13125+ // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
13126+ // can be specified by users through attributes property.
13127+ const paramType = getTypeAtPosition(signature, 0);
1312913128 const argType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined);
1313013129 const argProperties = getPropertiesOfType(argType);
1313113130 const paramProperties = getPropertiesOfType(paramType);
@@ -13146,6 +13145,9 @@ namespace ts {
1314613145 }
1314713146
1314813147 function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
13148+ if (isJsxOpeningLikeElement(node)) {
13149+ return checkApplicableSignatureForJsxOpeningLikeElement(<JsxOpeningLikeElement>node, signature, relation);
13150+ }
1314913151 const thisType = getThisTypeOfSignature(signature);
1315013152 if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) {
1315113153 // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType
@@ -13620,12 +13622,10 @@ namespace ts {
1362013622 return result;
1362113623 }
1362213624
13623- // Do not report any error if we are doing so for stateless function component as such error will be error will be handle in "resolveCustomJsxElementAttributesType".
1362413625 if (isJsxOpeningOrSelfClosingElement) {
13625- // If this is a type resolution session, e.g. Language Service, just return undefined as the language service can decide how to proceed with this failure.
13626- // (see getDefinitionAtPosition which simply get the symbol and return the first declaration of the JSXopeningLikeElement node)
13627- // otherwise, just return the latest signature candidate we try so far so that when we report an error we will get better error message.
13628- return produceDiagnostics ? candidateForArgumentError : undefined;
13626+ // If there is not result, just return the last one we try as a candidate.
13627+ // We do not report any error here because any error will be handled in "resolveCustomJsxElementAttributesType".
13628+ return candidateForArgumentError;
1362913629 }
1363013630
1363113631 // No signatures were applicable. Now report errors based on the last applicable signature with
@@ -13726,10 +13726,7 @@ namespace ts {
1372613726 }
1372713727 candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
1372813728 }
13729- if (isJsxOpeningOrSelfClosingElement && !checkApplicableSignatureForJsxOpeningLikeElement(<JsxOpeningLikeElement>node, candidate, relation)) {
13730- break;
13731- }
13732- else if (!isJsxOpeningOrSelfClosingElement && !checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
13729+ if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
1373313730 break;
1373413731 }
1373513732 const index = excludeArgument ? indexOf(excludeArgument, true) : -1;
@@ -14061,7 +14058,7 @@ namespace ts {
1406114058 }
1406214059 links.resolvedSignature = resolvingSignature;
1406314060
14064- let callSignature = resolvedStatelessJsxOpeningLikeElement (openingLikeElement, elementType, candidatesOutArray);
14061+ let callSignature = resolveStatelessJsxOpeningLikeElement (openingLikeElement, elementType, candidatesOutArray);
1406514062 if (!callSignature || callSignature === unknownSignature) {
1406614063 const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
1406714064 callSignature = callSignatures[callSignatures.length - 1];
@@ -14083,14 +14080,14 @@ namespace ts {
1408314080 * @return a resolved signature if we can find function matching function signature through resolve call or a first signature in the list of functions.
1408414081 * otherwise return undefined if tag-name of the opening-like element doesn't have call signatures
1408514082 */
14086- function resolvedStatelessJsxOpeningLikeElement (openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature {
14083+ function resolveStatelessJsxOpeningLikeElement (openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature {
1408714084 if (elementType.flags & TypeFlags.Union) {
1408814085 const types = (elementType as UnionType).types;
1408914086 let result: Signature;
14090- types.map( type => {
14087+ for (const type of types) {
1409114088 // This is mainly to fill in all the candidates if there is one.
14092- result = result || resolvedStatelessJsxOpeningLikeElement (openingLikeElement, type, candidatesOutArray);
14093- });
14089+ result = result || resolveStatelessJsxOpeningLikeElement (openingLikeElement, type, candidatesOutArray);
14090+ }
1409414091
1409514092 return result;
1409614093 }
@@ -14117,7 +14114,7 @@ namespace ts {
1411714114 return resolveDecorator(<Decorator>node, candidatesOutArray);
1411814115 case SyntaxKind.JsxOpeningElement:
1411914116 case SyntaxKind.JsxSelfClosingElement:
14120- return resolvedStatelessJsxOpeningLikeElement (<JsxOpeningLikeElement>node, checkExpression((<JsxOpeningLikeElement>node).tagName), candidatesOutArray);
14117+ return resolveStatelessJsxOpeningLikeElement (<JsxOpeningLikeElement>node, checkExpression((<JsxOpeningLikeElement>node).tagName), candidatesOutArray);
1412114118 }
1412214119 Debug.fail("Branch in 'resolveSignature' should be unreachable.");
1412314120 }
0 commit comments