Skip to content

Commit 6c20533

Browse files
committed
Improved error messages for invalid assignments to properties
1 parent 550be9c commit 6c20533

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11459,16 +11459,25 @@ namespace ts {
1145911459
}
1146011460

1146111461
const propType = getTypeOfSymbol(prop);
11462+
const assignmentKind = getAssignmentTargetKind(node);
11463+
11464+
if (assignmentKind) {
11465+
if (isReferenceToReadonlyEntity(<Expression>node, prop) || isReferenceThroughNamespaceImport(<Expression>node)) {
11466+
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, right.text);
11467+
return unknownType;
11468+
}
11469+
}
1146211470

1146311471
// Only compute control flow type if this is a property access expression that isn't an
1146411472
// assignment target, and the referenced property was declared as a variable, property,
1146511473
// accessor, or optional method.
11466-
if (node.kind !== SyntaxKind.PropertyAccessExpression || isAssignmentTarget(node) ||
11474+
if (node.kind !== SyntaxKind.PropertyAccessExpression || assignmentKind === AssignmentKind.Definite ||
1146711475
!(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) &&
1146811476
!(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) {
1146911477
return propType;
1147011478
}
11471-
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
11479+
const flowType = getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
11480+
return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
1147211481
}
1147311482

1147411483
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
@@ -13515,7 +13524,7 @@ namespace ts {
1351513524
error(expr, invalidReferenceMessage);
1351613525
return false;
1351713526
}
13518-
if (node.kind === SyntaxKind.Identifier) {
13527+
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression) {
1351913528
return true;
1352013529
}
1352113530
// Because we get the symbol from the resolvedSymbol property, it might be of kind

src/compiler/utilities.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1649,8 +1649,12 @@ namespace ts {
16491649
case SyntaxKind.SpreadElementExpression:
16501650
node = parent;
16511651
break;
1652-
case SyntaxKind.PropertyAssignment:
16531652
case SyntaxKind.ShorthandPropertyAssignment:
1653+
if ((<ShorthandPropertyAssignment>parent).name !== node) {
1654+
return AssignmentKind.None;
1655+
}
1656+
// Fall through
1657+
case SyntaxKind.PropertyAssignment:
16541658
node = parent.parent;
16551659
break;
16561660
default:

0 commit comments

Comments
 (0)