@@ -13212,6 +13212,8 @@ namespace ts {
13212
13212
let spread: Type = emptyObjectType;
13213
13213
let attributesArray: Symbol[] = [];
13214
13214
let hasSpreadAnyType = false;
13215
+ let explicitlySpecifyChildrenAttribute = false;
13216
+ const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
13215
13217
13216
13218
for (const attributeDecl of attributes.properties) {
13217
13219
const member = attributeDecl.symbol;
@@ -13230,6 +13232,9 @@ namespace ts {
13230
13232
attributeSymbol.target = member;
13231
13233
attributesTable.set(attributeSymbol.name, attributeSymbol);
13232
13234
attributesArray.push(attributeSymbol);
13235
+ if (attributeDecl.name.text === jsxChildrenPropertyName) {
13236
+ explicitlySpecifyChildrenAttribute = true;
13237
+ }
13233
13238
}
13234
13239
else {
13235
13240
Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute);
@@ -13290,8 +13295,7 @@ namespace ts {
13290
13295
13291
13296
// Error if there is a attribute named "children" and children element.
13292
13297
// This is because children element will overwrite the value from attributes
13293
- const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
13294
- if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
13298
+ if (explicitlySpecifyChildrenAttribute) {
13295
13299
if (attributesTable.has(jsxChildrenPropertyName)) {
13296
13300
error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName);
13297
13301
}
@@ -13314,7 +13318,7 @@ namespace ts {
13314
13318
*/
13315
13319
function createJsxAttributesType(symbol: Symbol, attributesTable: Map<Symbol>) {
13316
13320
const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
13317
- const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
13321
+ const freshObjectLiteralFlag = spread !== emptyObjectType || compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
13318
13322
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag;
13319
13323
result.objectFlags |= ObjectFlags.ObjectLiteral;
13320
13324
return result;
@@ -13866,7 +13870,15 @@ namespace ts {
13866
13870
error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, getJsxElementPropertiesName());
13867
13871
}
13868
13872
else {
13869
- checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
13873
+ const isAssignableToTargetAttributes = checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
13874
+ // TODO (yuisu): comment
13875
+ if (isAssignableToTargetAttributes && sourceAttributesType !== anyType && !(sourceAttributesType.flags & TypeFlags.FreshLiteral)) {
13876
+ for (const attribute of openingLikeElement.attributes.properties) {
13877
+ if (isJsxAttribute(attribute) && !getPropertyOfType(targetAttributesType, attribute.name.text)) {
13878
+ error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, attribute.name.text, typeToString(targetAttributesType));
13879
+ }
13880
+ }
13881
+ }
13870
13882
}
13871
13883
}
13872
13884
0 commit comments