Skip to content

Commit 788b2a3

Browse files
author
Yui T
committed
Wip - remove freshness flag from jsx attributes
1 parent d94d490 commit 788b2a3

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

src/compiler/checker.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13356,9 +13356,7 @@ namespace ts {
1335613356
*/
1335713357
function createJsxAttributesType(symbol: Symbol, attributesTable: Map<Symbol>) {
1335813358
const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
13359-
// Spread object doesn't have freshness flag to allow excess attributes as it is very common for parent component to spread its "props" to other components in its render method.
13360-
const freshObjectLiteralFlag = spread !== emptyObjectType || compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
13361-
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag;
13359+
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral;
1336213360
result.objectFlags |= ObjectFlags.ObjectLiteral;
1336313361
return result;
1336413362
}
@@ -13877,7 +13875,30 @@ namespace ts {
1387713875
checkJsxAttributesAssignableToTagNameAttributes(node);
1387813876
}
1387913877

13880-
/**
13878+
// Check if a property with the given name is known anywhere in the given type. In an object type, a property
13879+
// is considered known if the object type is empty and the check is for assignability, if the object type has
13880+
// index signatures, or if the property is actually declared in the object type. In a union or intersection
13881+
// type, a property is considered known if it is known in any constituent type.
13882+
function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean {
13883+
if (type.flags & TypeFlags.Object) {
13884+
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
13885+
if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) ||
13886+
getPropertyOfType(type, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
13887+
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
13888+
return true;
13889+
}
13890+
}
13891+
else if (type.flags & TypeFlags.UnionOrIntersection) {
13892+
for (const t of (<UnionOrIntersectionType>type).types) {
13893+
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
13894+
return true;
13895+
}
13896+
}
13897+
}
13898+
return false;
13899+
}
13900+
13901+
/**
1388113902
* Check whether the given attributes of JSX opening-like element is assignable to the tagName attributes.
1388213903
* Get the attributes type of the opening-like element through resolving the tagName, "target attributes"
1388313904
* Check assignablity between given attributes property, "source attributes", and the "target attributes"
@@ -13910,12 +13931,12 @@ namespace ts {
1391013931
}
1391113932
else {
1391213933
const isSourceAttributeTypeAssignableToTarget = checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
13913-
// If sourceAttributesType has spread (e.g the type doesn't have freshness flag) after we check for assignability, we will do another pass to check that
13934+
// After we check for assignability, we will do another pass to check that
1391413935
// all explicitly specified attributes have correct name corresponding with target (as those will be assignable as spread type allows excess properties)
1391513936
// Note: if the type of these explicitly specified attributes do not match it will be an error during above assignability check.
13916-
if (isSourceAttributeTypeAssignableToTarget && sourceAttributesType !== anyType && !(sourceAttributesType.flags & TypeFlags.FreshLiteral)) {
13937+
if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) {
1391713938
for (const attribute of openingLikeElement.attributes.properties) {
13918-
if (isJsxAttribute(attribute) && !getPropertyOfType(targetAttributesType, attribute.name.text)) {
13939+
if (isJsxAttribute(attribute) && !isKnownProperty(targetAttributesType, attribute.name.text, /*isComparingJsxAttributes*/ true)) {
1391913940
error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, attribute.name.text, typeToString(targetAttributesType));
1392013941
}
1392113942
}

0 commit comments

Comments
 (0)