@@ -10786,11 +10786,6 @@ namespace ts {
10786
10786
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag;
10787
10787
return result;
10788
10788
}
10789
-
10790
- function resolveCustomJsxElementAttributesTypeFromOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement) {
10791
- const symbolTable = getAttributesSymbolTableOfJsxOpeningLikeElement(openingLikeElement);
10792
- return createJsxAttributesType(openingLikeElement.attributes, symbolTable);
10793
- }
10794
10789
10795
10790
/**
10796
10791
* Check attributes type of intrinsic JSx opening-like element.
@@ -10827,39 +10822,21 @@ namespace ts {
10827
10822
checkAttributesTypeOfIntrinsicJsxOpeningLikeElement(openingLikeElement);
10828
10823
}
10829
10824
else {
10830
- const targetAttributesType = getAttributesTypeFromJsxOpeningLikeElement(openingLikeElement);
10831
- const sourceAttribtuesType = resolveCustomJsxElementAttributesTypeFromOpeningLikeElement(openingLikeElement);
10832
- const nameTable = createMap<boolean>();
10833
- // Process this array in right-to-left order so we know which
10834
- // attributes (mostly from spreads) are being overwritten and
10835
- // thus should have their types ignored
10836
- let sawSpreadedAny = false;
10837
- const attributes = openingLikeElement.attributes.properties;
10838
- for (let i = attributes.length - 1; i >= 0; i--) {
10839
- if (attributes[i].kind === SyntaxKind.JsxAttribute) {
10840
- checkJsxAttribute(<JsxAttribute>(attributes[i]), targetAttributesType, nameTable);
10841
- }
10842
- else {
10843
- Debug.assert(attributes[i].kind === SyntaxKind.JsxSpreadAttribute);
10844
- const spreadType = checkJsxSpreadAttribute(<JsxSpreadAttribute>(attributes[i]), targetAttributesType, nameTable);
10845
- if (isTypeAny(spreadType)) {
10846
- sawSpreadedAny = true;
10847
- }
10848
- }
10849
- }
10850
-
10851
- // Check that all required properties have been provided. If an 'any'
10852
- // was spreaded in, though, assume that it provided all required properties
10853
- if (targetAttributesType && !sawSpreadedAny) {
10854
- const targetProperties = getPropertiesOfType(targetAttributesType);
10855
- for (let i = 0; i < targetProperties.length; i++) {
10856
- if (!(targetProperties[i].flags & SymbolFlags.Optional) &&
10857
- !nameTable[targetProperties[i].name]) {
10858
-
10859
- error(openingLikeElement, Diagnostics.Property_0_is_missing_in_type_1, targetProperties[i].name, typeToString(targetAttributesType));
10825
+ const targetAttributesType = getCustomJsxElementAttributesType(openingLikeElement);
10826
+ const symbolTable = getAttributesSymbolTableOfJsxOpeningLikeElement(openingLikeElement);
10827
+ // Filter out any hyphenated names as those are not play any role in type-checking unless there are corresponding properties in the target type
10828
+ let attributesTable: Map<Symbol>;
10829
+ let sourceAttributesType = anyType as Type;
10830
+ if (symbolTable) {
10831
+ attributesTable = createMap<Symbol>();
10832
+ for (const key in symbolTable) {
10833
+ if (isUnhyphenatedJsxName(key) || getPropertyOfType(targetAttributesType, key)) {
10834
+ attributesTable[key] = symbolTable[key];
10860
10835
}
10861
10836
}
10837
+ sourceAttributesType = createJsxAttributesType(openingLikeElement.attributes, attributesTable);
10862
10838
}
10839
+ checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
10863
10840
}
10864
10841
}
10865
10842
@@ -11037,22 +11014,22 @@ namespace ts {
11037
11014
}
11038
11015
11039
11016
/**
11040
- * Resolve attributes type of the given node. The function is intended to initally be called from getAttributesTypeFromJsxOpeningLikeElement which already handle JSX-intrinsic-element.
11041
- * @param openingLikeElement a non-instrinsic JSXOPeningLikeElement
11017
+ * Resolve attributes type of the given node. The function is intended to initially be called from getAttributesTypeFromJsxOpeningLikeElement which already handle JSX-intrinsic-element.
11018
+ * @param openingLikeElement a non-intrinsic JSXOPeningLikeElement
11042
11019
* @param elementType an instance type of the given node
11043
11020
* @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global (imported from react.d.ts)
11044
11021
* @return attributes'type if able to resolve the type of node
11045
11022
* anyType if there is no type ElementAttributesProperty or there is an error
11046
11023
* emptyObjectType if there is no "prop" in the element instance type
11047
11024
**/
11048
- function resolveJsxElementAttributesType (openingLikeElement: JsxOpeningLikeElement, elementType?: Type, elementClassType?: Type): Type {
11025
+ function resolveCustomJsxElementAttributesType (openingLikeElement: JsxOpeningLikeElement, elementType?: Type, elementClassType?: Type): Type {
11049
11026
if (!elementType) {
11050
11027
elementType = checkExpression(openingLikeElement.tagName);
11051
11028
}
11052
11029
if (elementType.flags & TypeFlags.Union) {
11053
11030
const types = (<TypeOperatorType>elementType).types;
11054
11031
return getUnionType(types.map(type => {
11055
- return resolveJsxElementAttributesType (openingLikeElement, type, elementClassType);
11032
+ return resolveCustomJsxElementAttributesType (openingLikeElement, type, elementClassType);
11056
11033
}), /*subtypeReduction*/ true);
11057
11034
}
11058
11035
@@ -11062,6 +11039,9 @@ namespace ts {
11062
11039
}
11063
11040
else if (elementType.flags & TypeFlags.StringLiteral) {
11064
11041
// If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type
11042
+ // For example:
11043
+ // var CustomTag: "h1" = "h1";
11044
+ // <CustomTag> Hello World </CustomTag>
11065
11045
const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements);
11066
11046
if (intrinsicElementsType !== unknownType) {
11067
11047
const stringLiteralTypeName = (<LiteralType>elementType).text;
@@ -11086,8 +11066,8 @@ namespace ts {
11086
11066
// Is this is a stateless function component? See if its single signature's return type is
11087
11067
// assignable to the JSX Element Type
11088
11068
if (jsxElementType) {
11089
- const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
11090
- const callSignature = callSignatures && callSignatures.length > 0 && callSignatures[0] ;
11069
+ // TODO (yuisu) : comment
11070
+ const callSignature = getResolvedSignature(openingLikeElement) ;
11091
11071
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
11092
11072
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
11093
11073
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
@@ -11185,14 +11165,14 @@ namespace ts {
11185
11165
11186
11166
/**
11187
11167
* Get attributes type of the given custom opening-like Jsx element.
11188
- * The function is intended to be called from a function which has handle intrinsic Jsx element.
11168
+ * The function is intended to be called from a function which has handle intrinsic Jsx element already .
11189
11169
* @param node a custom Jsx opening-like element
11190
11170
*/
11191
- function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement ): Type {
11171
+ function getCustomJsxElementAttributesType(node: JsxOpeningElement ): Type {
11192
11172
const links = getNodeLinks(node);
11193
11173
if (!links.resolvedJsxElementAttributesType) {
11194
11174
const elemClassType = getJsxGlobalElementClassType();
11195
- return links.resolvedJsxElementAttributesType = resolveJsxElementAttributesType (node, undefined, elemClassType);
11175
+ return links.resolvedJsxElementAttributesType = resolveCustomJsxElementAttributesType (node, undefined, elemClassType);
11196
11176
}
11197
11177
return links.resolvedJsxElementAttributesType;
11198
11178
}
@@ -11787,6 +11767,11 @@ namespace ts {
11787
11767
let isDecorator: boolean;
11788
11768
let spreadArgIndex = -1;
11789
11769
11770
+ /// TODO(Yuisu): comment
11771
+ if (node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement) {
11772
+ return true;
11773
+ }
11774
+
11790
11775
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
11791
11776
const tagExpression = <TaggedTemplateExpression>node;
11792
11777
@@ -12068,6 +12053,9 @@ namespace ts {
12068
12053
// `getEffectiveArgumentCount` and `getEffectiveArgumentType` below.
12069
12054
return undefined;
12070
12055
}
12056
+ else if (node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement) {
12057
+ args = [(<JsxOpeningLikeElement>node).attributes];
12058
+ }
12071
12059
else {
12072
12060
args = (<CallExpression>node).arguments || emptyArray;
12073
12061
}
@@ -12311,6 +12299,14 @@ namespace ts {
12311
12299
else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) {
12312
12300
return getGlobalTemplateStringsArrayType();
12313
12301
}
12302
+ else if (node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement) {
12303
+ const symbolTable = getAttributesSymbolTableOfJsxOpeningLikeElement(node as JsxOpeningLikeElement);
12304
+ let argAttributesType = anyType as Type;
12305
+ if (symbolTable) {
12306
+ argAttributesType = createJsxAttributesType((<JsxOpeningLikeElement>node).attributes, symbolTable);
12307
+ }
12308
+ return argAttributesType;
12309
+ }
12314
12310
12315
12311
// This is not a synthetic argument, so we return 'undefined'
12316
12312
// to signal that the caller needs to check the argument.
@@ -12350,10 +12346,11 @@ namespace ts {
12350
12346
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], headMessage?: DiagnosticMessage): Signature {
12351
12347
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
12352
12348
const isDecorator = node.kind === SyntaxKind.Decorator;
12349
+ const isJsxOpeningLikeElement = node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement;
12353
12350
12354
12351
let typeArguments: TypeNode[];
12355
12352
12356
- if (!isTaggedTemplate && !isDecorator) {
12353
+ if (!isTaggedTemplate && !isDecorator && !isJsxOpeningLikeElement ) {
12357
12354
typeArguments = (<CallExpression>node).typeArguments;
12358
12355
12359
12356
// We already perform checking on the type arguments on the class declaration itself.
@@ -12465,7 +12462,8 @@ namespace ts {
12465
12462
// in arguments too early. If possible, we'd like to only type them once we know the correct
12466
12463
// overload. However, this matters for the case where the call is correct. When the call is
12467
12464
// an error, we don't need to exclude any arguments, although it would cause no harm to do so.
12468
- checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
12465
+ // TODO (yuisu): comment
12466
+ checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ isJsxOpeningLikeElement ? false: true);
12469
12467
}
12470
12468
else if (candidateForTypeArgumentError) {
12471
12469
if (!isTaggedTemplate && !isDecorator && typeArguments) {
@@ -12511,6 +12509,9 @@ namespace ts {
12511
12509
return resolveErrorCall(node);
12512
12510
12513
12511
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
12512
+ if (isJsxOpeningLikeElement) {
12513
+ return;
12514
+ }
12514
12515
let errorInfo: DiagnosticMessageChain;
12515
12516
errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
12516
12517
if (headMessage) {
@@ -12862,6 +12863,24 @@ namespace ts {
12862
12863
return resolveCall(node, callSignatures, candidatesOutArray, headMessage);
12863
12864
}
12864
12865
12866
+ /**
12867
+ *
12868
+ * @param node
12869
+ * @param candidatesOutArray
12870
+ */
12871
+ function resolveStateLessJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[]): Signature | undefined {
12872
+ const elementType = checkExpression(node.tagName);
12873
+ const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
12874
+
12875
+ if (callSignatures && callSignatures.length > 0) {
12876
+ let callSignature: Signature;
12877
+ callSignature = resolveCall(node, callSignatures, candidatesOutArray) || callSignatures[0];
12878
+ return callSignature
12879
+ }
12880
+
12881
+ return undefined;
12882
+ }
12883
+
12865
12884
function resolveSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
12866
12885
switch (node.kind) {
12867
12886
case SyntaxKind.CallExpression:
@@ -12872,6 +12891,9 @@ namespace ts {
12872
12891
return resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
12873
12892
case SyntaxKind.Decorator:
12874
12893
return resolveDecorator(<Decorator>node, candidatesOutArray);
12894
+ case SyntaxKind.JsxOpeningElement:
12895
+ case SyntaxKind.JsxSelfClosingElement:
12896
+ return resolveStateLessJsxOpeningLikeElement(<JsxOpeningLikeElement>node, candidatesOutArray);
12875
12897
}
12876
12898
Debug.fail("Branch in 'resolveSignature' should be unreachable.");
12877
12899
}
0 commit comments