@@ -8851,7 +8851,7 @@ namespace ts {
8851
8851
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
8852
8852
// only need to evaluate the assigned type if the declared type is a union type.
8853
8853
if (isMatchingReference(reference, node)) {
8854
- if (node.parent.kind === SyntaxKind.PrefixUnaryExpression || node.parent.kind === SyntaxKind.PostfixUnaryExpression ) {
8854
+ if (getAssignmentTargetKind( node) === AssignmentKind.Compound ) {
8855
8855
const flowType = getTypeAtFlowNode(flow.antecedent);
8856
8856
return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
8857
8857
}
@@ -9298,10 +9298,10 @@ namespace ts {
9298
9298
}
9299
9299
}
9300
9300
else {
9301
- const invokedExpression = skipParenthesizedNodes (callExpression.expression);
9301
+ const invokedExpression = skipParentheses (callExpression.expression);
9302
9302
if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) {
9303
9303
const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression;
9304
- const possibleReference = skipParenthesizedNodes (accessExpression.expression);
9304
+ const possibleReference = skipParentheses (accessExpression.expression);
9305
9305
if (isMatchingReference(reference, possibleReference)) {
9306
9306
return getNarrowedType(type, predicate.type, assumeTrue);
9307
9307
}
@@ -9361,13 +9361,6 @@ namespace ts {
9361
9361
return getTypeOfSymbol(symbol);
9362
9362
}
9363
9363
9364
- function skipParenthesizedNodes(expression: Expression): Expression {
9365
- while (expression.kind === SyntaxKind.ParenthesizedExpression) {
9366
- expression = (expression as ParenthesizedExpression).expression;
9367
- }
9368
- return expression;
9369
- }
9370
-
9371
9364
function getControlFlowContainer(node: Node): Node {
9372
9365
while (true) {
9373
9366
node = node.parent;
@@ -9425,6 +9418,9 @@ namespace ts {
9425
9418
9426
9419
function checkIdentifier(node: Identifier): Type {
9427
9420
const symbol = getResolvedSymbol(node);
9421
+ if (symbol === unknownSymbol) {
9422
+ return unknownType;
9423
+ }
9428
9424
9429
9425
// As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects.
9430
9426
// Although in down-level emit of arrow function, we emit it using function expression which means that
@@ -9446,6 +9442,7 @@ namespace ts {
9446
9442
if (node.flags & NodeFlags.AwaitContext) {
9447
9443
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
9448
9444
}
9445
+ return getTypeOfSymbol(symbol);
9449
9446
}
9450
9447
9451
9448
if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
@@ -9498,9 +9495,22 @@ namespace ts {
9498
9495
9499
9496
const type = getTypeOfSymbol(localOrExportSymbol);
9500
9497
const declaration = localOrExportSymbol.valueDeclaration;
9498
+ const assignmentKind = getAssignmentTargetKind(node);
9499
+
9500
+ if (assignmentKind) {
9501
+ if (!(localOrExportSymbol.flags & SymbolFlags.Variable)) {
9502
+ error(node, Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol));
9503
+ return unknownType;
9504
+ }
9505
+ if (isReadonlySymbol(localOrExportSymbol)) {
9506
+ error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(symbol));
9507
+ return unknownType;
9508
+ }
9509
+ }
9510
+
9501
9511
// We only narrow variables and parameters occurring in a non-assignment position. For all other
9502
9512
// entities we simply return the declared type.
9503
- if (!(localOrExportSymbol.flags & SymbolFlags.Variable) || isAssignmentTarget(node) || !declaration) {
9513
+ if (!(localOrExportSymbol.flags & SymbolFlags.Variable) || assignmentKind === AssignmentKind.Definite || !declaration) {
9504
9514
return type;
9505
9515
}
9506
9516
// The declaration container is the innermost function that encloses the declaration of the variable
@@ -9542,7 +9552,7 @@ namespace ts {
9542
9552
// Return the declared type to reduce follow-on errors
9543
9553
return type;
9544
9554
}
9545
- return flowType;
9555
+ return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
9546
9556
}
9547
9557
9548
9558
function isInsideFunction(node: Node, threshold: Node): boolean {
@@ -11397,6 +11407,20 @@ namespace ts {
11397
11407
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
11398
11408
}
11399
11409
11410
+ function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
11411
+ let errorInfo: DiagnosticMessageChain;
11412
+ if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
11413
+ for (const subtype of (containingType as UnionType).types) {
11414
+ if (!getPropertyOfType(subtype, propNode.text)) {
11415
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype));
11416
+ break;
11417
+ }
11418
+ }
11419
+ }
11420
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
11421
+ diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
11422
+ }
11423
+
11400
11424
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
11401
11425
const type = checkNonNullExpression(left);
11402
11426
if (isTypeAny(type) || type === silentNeverType) {
@@ -11445,20 +11469,6 @@ namespace ts {
11445
11469
return propType;
11446
11470
}
11447
11471
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
11448
-
11449
- function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
11450
- let errorInfo: DiagnosticMessageChain;
11451
- if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
11452
- for (const subtype of (containingType as UnionType).types) {
11453
- if (!getPropertyOfType(subtype, propNode.text)) {
11454
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype));
11455
- break;
11456
- }
11457
- }
11458
- }
11459
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
11460
- diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
11461
- }
11462
11472
}
11463
11473
11464
11474
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
@@ -11505,7 +11515,7 @@ namespace ts {
11505
11515
* that references a for-in variable for an object with numeric property names.
11506
11516
*/
11507
11517
function isForInVariableForNumericPropertyNames(expr: Expression) {
11508
- const e = skipParenthesizedNodes (expr);
11518
+ const e = skipParentheses (expr);
11509
11519
if (e.kind === SyntaxKind.Identifier) {
11510
11520
const symbol = getResolvedSymbol(<Identifier>e);
11511
11521
if (symbol.flags & SymbolFlags.Variable) {
@@ -13486,7 +13496,7 @@ namespace ts {
13486
13496
13487
13497
function isReferenceThroughNamespaceImport(expr: Expression): boolean {
13488
13498
if (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) {
13489
- const node = skipParenthesizedNodes ((expr as PropertyAccessExpression | ElementAccessExpression).expression);
13499
+ const node = skipParentheses ((expr as PropertyAccessExpression | ElementAccessExpression).expression);
13490
13500
if (node.kind === SyntaxKind.Identifier) {
13491
13501
const symbol = getNodeLinks(node).resolvedSymbol;
13492
13502
if (symbol.flags & SymbolFlags.Alias) {
@@ -13500,11 +13510,14 @@ namespace ts {
13500
13510
13501
13511
function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage, constantVariableMessage: DiagnosticMessage): boolean {
13502
13512
// References are combinations of identifiers, parentheses, and property accesses.
13503
- const node = skipParenthesizedNodes (expr);
13513
+ const node = skipParentheses (expr);
13504
13514
if (node.kind !== SyntaxKind.Identifier && node.kind !== SyntaxKind.PropertyAccessExpression && node.kind !== SyntaxKind.ElementAccessExpression) {
13505
13515
error(expr, invalidReferenceMessage);
13506
13516
return false;
13507
13517
}
13518
+ if (node.kind === SyntaxKind.Identifier) {
13519
+ return true;
13520
+ }
13508
13521
// Because we get the symbol from the resolvedSymbol property, it might be of kind
13509
13522
// SymbolFlags.ExportValue. In this case it is necessary to get the actual export
13510
13523
// symbol, which will have the correct flags set on it.
@@ -13514,10 +13527,10 @@ namespace ts {
13514
13527
if (symbol !== unknownSymbol && symbol !== argumentsSymbol) {
13515
13528
// Only variables (and not functions, classes, namespaces, enum objects, or enum members)
13516
13529
// are considered references when referenced using a simple identifier.
13517
- if (node.kind === SyntaxKind.Identifier && !(symbol.flags & SymbolFlags.Variable)) {
13518
- error(expr, invalidReferenceMessage);
13519
- return false;
13520
- }
13530
+ // if (node.kind === SyntaxKind.Identifier && !(symbol.flags & SymbolFlags.Variable)) {
13531
+ // error(expr, invalidReferenceMessage);
13532
+ // return false;
13533
+ // }
13521
13534
if (isReferenceToReadonlyEntity(node, symbol) || isReferenceThroughNamespaceImport(node)) {
13522
13535
error(expr, constantVariableMessage);
13523
13536
return false;
@@ -14255,7 +14268,7 @@ namespace ts {
14255
14268
}
14256
14269
14257
14270
function isTypeAssertion(node: Expression) {
14258
- node = skipParenthesizedNodes (node);
14271
+ node = skipParentheses (node);
14259
14272
return node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression;
14260
14273
}
14261
14274
0 commit comments