Skip to content

Commit 1512028

Browse files
committed
check both prefix + postfix unary expressions
1 parent f235b37 commit 1512028

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13268,6 +13268,11 @@ namespace ts {
1326813268
isUnitType(type);
1326913269
}
1327013270

13271+
function isStringOrNumericLiteralType(type: Type): boolean {
13272+
return type.flags & TypeFlags.Union ? every((<UnionType>type).types, t => !!(t.flags & TypeFlags.StringOrNumberLiteral && !(t.flags & (TypeFlags.EnumLike | TypeFlags.Intrinsic)))) :
13273+
!!(type.flags & TypeFlags.StringOrNumberLiteral) && !(type.flags & (TypeFlags.EnumLike | TypeFlags.Intrinsic))
13274+
}
13275+
1327113276
function getBaseTypeOfLiteralType(type: Type): Type {
1327213277
return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(<LiteralType>type) :
1327313278
type.flags & TypeFlags.StringLiteral ? stringType :
@@ -21803,17 +21808,7 @@ namespace ts {
2180321808
}
2180421809

2180521810
function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type {
21806-
let operandType: Type;
21807-
const symbol = isEntityNameExpression(node.operand) ? isPropertyAccessEntityNameExpression(node.operand) ?
21808-
getSymbolAtLocation((<PropertyAccessExpression>node.operand).name) : getResolvedSymbol(node.operand as Identifier) : undefined;
21809-
if (symbol && !(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const)) {
21810-
operandType = getTypeOfSymbol(symbol);
21811-
if (isLiteralType(operandType) && !(operandType.flags & (TypeFlags.EnumLike | TypeFlags.BooleanLike | TypeFlags.Undefined))) {
21812-
error(node.operand, Diagnostics.The_literal_type_0_cannot_be_modified, typeToString(operandType));
21813-
}
21814-
}
21815-
operandType = checkExpression(node.operand);
21816-
21811+
const operandType = checkExpression(node.operand);
2181721812
if (operandType === silentNeverType) {
2181821813
return silentNeverType;
2181921814
}
@@ -21838,6 +21833,21 @@ namespace ts {
2183821833
return numberType;
2183921834
}
2184021835

21836+
function checkUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression): Type {
21837+
const symbol = isEntityNameExpression(node.operand) ? isPropertyAccessEntityNameExpression(node.operand) ?
21838+
getSymbolAtLocation((<PropertyAccessExpression>node.operand).name) : getResolvedSymbol(node.operand as Identifier) : undefined;
21839+
if (symbol && isUnaryAssignmentOperator(node.operator) && !(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const)) {
21840+
const operandType = getTypeOfSymbol(symbol);
21841+
if (isStringOrNumericLiteralType(operandType)) {
21842+
error(node.operand, Diagnostics.The_literal_type_0_cannot_be_modified, typeToString(operandType));
21843+
}
21844+
}
21845+
if (node.kind == SyntaxKind.PrefixUnaryExpression) {
21846+
return checkPrefixUnaryExpression(node)
21847+
}
21848+
return checkPostfixUnaryExpression(node)
21849+
}
21850+
2184121851
// Return true if type might be of the given kind. A union or intersection type might be of a given
2184221852
// kind if at least one constituent type is of the given kind.
2184321853
function maybeTypeOfKind(type: Type, kind: TypeFlags): boolean {
@@ -22186,7 +22196,7 @@ namespace ts {
2218622196
getSymbolAtLocation((<PropertyAccessExpression>left).name) : getResolvedSymbol(left as Identifier) : undefined;
2218722197
if (symbol && isCompoundAssignmentOperator(operator) && !(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const)) {
2218822198
leftType = getTypeOfSymbol(getResolvedSymbol(left as Identifier));
22189-
if (isLiteralType(leftType) && !(leftType.flags & (TypeFlags.EnumLike | TypeFlags.BooleanLike | TypeFlags.Undefined))) {
22199+
if (isStringOrNumericLiteralType(leftType)) {
2219022200
error(left, Diagnostics.The_literal_type_0_cannot_be_modified, typeToString(leftType));
2219122201
}
2219222202
}
@@ -22885,9 +22895,8 @@ namespace ts {
2288522895
case SyntaxKind.AwaitExpression:
2288622896
return checkAwaitExpression(<AwaitExpression>node);
2288722897
case SyntaxKind.PrefixUnaryExpression:
22888-
return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
2288922898
case SyntaxKind.PostfixUnaryExpression:
22890-
return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
22899+
return checkUnaryExpression(<PrefixUnaryExpression | PostfixUnaryExpression>node);
2289122900
case SyntaxKind.BinaryExpression:
2289222901
return checkBinaryExpression(<BinaryExpression>node, checkMode);
2289322902
case SyntaxKind.ConditionalExpression:

src/compiler/utilities.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3854,6 +3854,12 @@ namespace ts {
38543854
|| token === SyntaxKind.GreaterThanGreaterThanEqualsToken;
38553855
}
38563856

3857+
export function isUnaryAssignmentOperator(token: SyntaxKind): boolean {
3858+
return token === SyntaxKind.PlusPlusToken
3859+
|| token === SyntaxKind.MinusMinusToken
3860+
3861+
}
3862+
38573863
export function isAssignmentOperator(token: SyntaxKind): boolean {
38583864
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
38593865
}

0 commit comments

Comments
 (0)