Skip to content

Commit acf78b7

Browse files
author
Yui T
committed
Wip - remove freshness flag from jsx attributes
1 parent 64d301b commit acf78b7

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
@@ -13319,9 +13319,7 @@ namespace ts {
1331913319
*/
1332013320
function createJsxAttributesType(symbol: Symbol, attributesTable: Map<Symbol>) {
1332113321
const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
13322-
// 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.
13323-
const freshObjectLiteralFlag = spread !== emptyObjectType || compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
13324-
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag;
13322+
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral;
1332513323
result.objectFlags |= ObjectFlags.ObjectLiteral;
1332613324
return result;
1332713325
}
@@ -13840,7 +13838,30 @@ namespace ts {
1384013838
checkJsxAttributesAssignableToTagNameAttributes(node);
1384113839
}
1384213840

13843-
/**
13841+
// Check if a property with the given name is known anywhere in the given type. In an object type, a property
13842+
// is considered known if the object type is empty and the check is for assignability, if the object type has
13843+
// index signatures, or if the property is actually declared in the object type. In a union or intersection
13844+
// type, a property is considered known if it is known in any constituent type.
13845+
function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean {
13846+
if (type.flags & TypeFlags.Object) {
13847+
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
13848+
if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) ||
13849+
getPropertyOfType(type, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
13850+
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
13851+
return true;
13852+
}
13853+
}
13854+
else if (type.flags & TypeFlags.UnionOrIntersection) {
13855+
for (const t of (<UnionOrIntersectionType>type).types) {
13856+
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
13857+
return true;
13858+
}
13859+
}
13860+
}
13861+
return false;
13862+
}
13863+
13864+
/**
1384413865
* Check whether the given attributes of JSX opening-like element is assignable to the tagName attributes.
1384513866
* Get the attributes type of the opening-like element through resolving the tagName, "target attributes"
1384613867
* Check assignablity between given attributes property, "source attributes", and the "target attributes"
@@ -13873,12 +13894,12 @@ namespace ts {
1387313894
}
1387413895
else {
1387513896
const isSourceAttributeTypeAssignableToTarget = checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
13876-
// 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
13897+
// After we check for assignability, we will do another pass to check that
1387713898
// all explicitly specified attributes have correct name corresponding with target (as those will be assignable as spread type allows excess properties)
1387813899
// Note: if the type of these explicitly specified attributes do not match it will be an error during above assignability check.
13879-
if (isSourceAttributeTypeAssignableToTarget && sourceAttributesType !== anyType && !(sourceAttributesType.flags & TypeFlags.FreshLiteral)) {
13900+
if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) {
1388013901
for (const attribute of openingLikeElement.attributes.properties) {
13881-
if (isJsxAttribute(attribute) && !getPropertyOfType(targetAttributesType, attribute.name.text)) {
13902+
if (isJsxAttribute(attribute) && !isKnownProperty(targetAttributesType, attribute.name.text, /*isComparingJsxAttributes*/ true)) {
1388213903
error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, attribute.name.text, typeToString(targetAttributesType));
1388313904
}
1388413905
}

0 commit comments

Comments
 (0)