Skip to content

Commit 747f50f

Browse files
migrate checkDelete to new property checking
1 parent 8ea8044 commit 747f50f

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5777,7 +5777,7 @@ namespace ts {
57775777
getIndexInfoOfType(objectType, IndexKind.String) ||
57785778
undefined;
57795779
if (indexInfo) {
5780-
if (accessExpression && isAssignmentTarget(accessExpression) && indexInfo.isReadonly) {
5780+
if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
57815781
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
57825782
return unknownType;
57835783
}
@@ -13550,9 +13550,16 @@ namespace ts {
1355013550

1355113551
function checkDeleteExpression(node: DeleteExpression): Type {
1355213552
checkExpression(node.expression);
13553-
checkReferenceExpression(node.expression,
13554-
Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference,
13555-
Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
13553+
const expr = skipParentheses(node.expression);
13554+
if (expr.kind !== SyntaxKind.PropertyAccessExpression && expr.kind !== SyntaxKind.ElementAccessExpression) {
13555+
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference);
13556+
return booleanType;
13557+
}
13558+
const links = getNodeLinks(expr);
13559+
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
13560+
if (symbol && isReadonlySymbol(symbol)) {
13561+
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
13562+
}
1355613563
return booleanType;
1355713564
}
1355813565

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2651,7 +2651,6 @@ namespace ts {
26512651
resolvedType?: Type; // Cached type of type node
26522652
resolvedSignature?: Signature; // Cached signature of signature node or call expression
26532653
resolvedSymbol?: Symbol; // Cached name resolution result
2654-
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
26552654
enumMemberValue?: number; // Constant value of enum member
26562655
isVisible?: boolean; // Is this node visible
26572656
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context

src/compiler/utilities.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="sys.ts" />
1+
/// <reference path="sys.ts" />
22

33
/* @internal */
44
namespace ts {
@@ -1666,6 +1666,18 @@ namespace ts {
16661666
return getAssignmentTargetKind(node) !== AssignmentKind.None;
16671667
}
16681668

1669+
// a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped
1670+
export function isDeleteTarget(node: Node): boolean {
1671+
if (node.kind !== SyntaxKind.PropertyAccessExpression && node.kind !== SyntaxKind.ElementAccessExpression) {
1672+
return false;
1673+
}
1674+
node = node.parent;
1675+
while (node && node.kind === SyntaxKind.ParenthesizedExpression) {
1676+
node = node.parent;
1677+
}
1678+
return node && node.kind === SyntaxKind.DeleteExpression;
1679+
}
1680+
16691681
export function isNodeDescendantOf(node: Node, ancestor: Node): boolean {
16701682
while (node) {
16711683
if (node === ancestor) return true;

0 commit comments

Comments
 (0)