Fix compound assignments for properties with different getter & setter types (#50431)

This commit is contained in:
jihndai
2023-03-07 16:02:16 -08:00
committed by GitHub
parent d747277edf
commit 4af97b0572
70 changed files with 937 additions and 313 deletions
+15 -7
View File
@@ -33,6 +33,7 @@ import {
BigIntLiteral,
BigIntLiteralType,
BinaryExpression,
BinaryOperator,
BinaryOperatorToken,
binarySearch,
BindableObjectDefinePropertyCall,
@@ -471,6 +472,7 @@ import {
isCommaSequence,
isCommonJsExportedExpression,
isCommonJsExportPropertyAssignment,
isCompoundAssignment,
isComputedNonLiteralName,
isComputedPropertyName,
isConstructorDeclaration,
@@ -31059,9 +31061,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return nonNullType;
}
function checkPropertyAccessExpression(node: PropertyAccessExpression, checkMode: CheckMode | undefined) {
function checkPropertyAccessExpression(node: PropertyAccessExpression, checkMode: CheckMode | undefined, writeOnly?: boolean) {
return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain, checkMode) :
checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name, checkMode);
checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name, checkMode, writeOnly);
}
function checkPropertyAccessChain(node: PropertyAccessChain, checkMode: CheckMode | undefined) {
@@ -31204,7 +31206,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
&& getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) === getDeclaringConstructor(prop);
}
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined) {
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined, writeOnly?: boolean) {
const parentSymbol = getNodeLinks(left).resolvedSymbol;
const assignmentKind = getAssignmentTargetKind(node);
const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
@@ -31312,14 +31314,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, isSelfTypeAccess(left, parentSymbol));
getNodeLinks(node).resolvedSymbol = prop;
const writing = isWriteAccess(node);
checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, writing, apparentType, prop);
checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, isWriteAccess(node), apparentType, prop);
if (isAssignmentToReadonlyEntity(node as Expression, prop, assignmentKind)) {
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, idText(right));
return errorType;
}
propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writeOnly || isWriteOnlyAccess(node) ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
}
return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode);
@@ -36811,6 +36812,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function checkAssignmentOperatorWorker() {
let assigneeType = leftType;
// getters can be a subtype of setters, so to check for assignability we use the setter's type instead
if (isCompoundAssignment(operatorToken.kind as BinaryOperator) && left.kind === SyntaxKind.PropertyAccessExpression) {
assigneeType = checkPropertyAccessExpression(left as PropertyAccessExpression, /*checkMode*/ undefined, /*writeOnly*/ true);
}
// TypeScript 1.0 spec (April 2014): 4.17
// An assignment of the form
// VarExpr = ValueExpr
@@ -36831,7 +36839,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
checkTypeAssignableToAndOptionallyElaborate(valueType, leftType, left, right, headMessage);
checkTypeAssignableToAndOptionallyElaborate(valueType, assigneeType, left, right, headMessage);
}
}
}
+5 -11
View File
@@ -7491,26 +7491,25 @@ export function isWriteAccess(node: Node) {
const enum AccessKind {
/** Only reads from a variable. */
Read,
/** Only writes to a variable without using the result. E.g.: `x++;`. */
/** Only writes to a variable without ever reading it. E.g.: `x=1;`. */
Write,
/** Writes to a variable and uses the result as an expression. E.g.: `f(x++);`. */
/** Reads from and writes to a variable. E.g.: `f(x++);`, `x/=1`. */
ReadWrite
}
function accessKind(node: Node): AccessKind {
const { parent } = node;
if (!parent) return AccessKind.Read;
switch (parent.kind) {
switch (parent?.kind) {
case SyntaxKind.ParenthesizedExpression:
return accessKind(parent);
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
const { operator } = parent as PrefixUnaryExpression | PostfixUnaryExpression;
return operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken ? writeOrReadWrite() : AccessKind.Read;
return operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken ? AccessKind.ReadWrite : AccessKind.Read;
case SyntaxKind.BinaryExpression:
const { left, operatorToken } = parent as BinaryExpression;
return left === node && isAssignmentOperator(operatorToken.kind) ?
operatorToken.kind === SyntaxKind.EqualsToken ? AccessKind.Write : writeOrReadWrite()
operatorToken.kind === SyntaxKind.EqualsToken ? AccessKind.Write : AccessKind.ReadWrite
: AccessKind.Read;
case SyntaxKind.PropertyAccessExpression:
return (parent as PropertyAccessExpression).name !== node ? AccessKind.Read : accessKind(parent);
@@ -7527,11 +7526,6 @@ function accessKind(node: Node): AccessKind {
default:
return AccessKind.Read;
}
function writeOrReadWrite(): AccessKind {
// If grandparent is not an ExpressionStatement, this is used as an expression in addition to having a side effect.
return parent.parent && walkUpParenthesizedExpressions(parent.parent).kind === SyntaxKind.ExpressionStatement ? AccessKind.Write : AccessKind.ReadWrite;
}
}
function reverseAccessKind(a: AccessKind): AccessKind {
switch (a) {
@@ -0,0 +1,161 @@
//// [getterSetterSubtypeAssignment.ts]
class NumberOrUndefined {
_x: number | undefined;
get x(): number { return this._x ?? 0; }
set x(value: number | undefined) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrUndefined = new NumberOrUndefined();
numberOrUndefined.x += 1;
numberOrUndefined.x -= 1;
numberOrUndefined.x *= 1;
numberOrUndefined.x /= 1;
class NumberOrString {
_x: number | string = 0;
get x(): number { return typeof this._x === 'number' ? this._x : Number(this._x); }
set x(value: number | string) { this._x = value; }
additionAssignmentNumber() {
this.x += 1;
}
additionAssignmentString() {
this.x += '1';
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrString = new NumberOrString();
numberOrString.x += 1;
numberOrString.x += '1';
numberOrString.x -= 1;
numberOrString.x *= 1;
numberOrString.x /= 1;
type Foo = { bar: number; };
class NumberOrObject {
_x: number | Foo = 0;
get x(): number { return typeof this._x === 'number' ? this._x : this._x.bar; }
set x(value: number | Foo) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrObject = new NumberOrObject();
numberOrObject.x += 1;
numberOrObject.x -= 1;
numberOrObject.x *= 1;
numberOrObject.x /= 1;
//// [getterSetterSubtypeAssignment.js]
class NumberOrUndefined {
get x() { var _a; return (_a = this._x) !== null && _a !== void 0 ? _a : 0; }
set x(value) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrUndefined = new NumberOrUndefined();
numberOrUndefined.x += 1;
numberOrUndefined.x -= 1;
numberOrUndefined.x *= 1;
numberOrUndefined.x /= 1;
class NumberOrString {
constructor() {
this._x = 0;
}
get x() { return typeof this._x === 'number' ? this._x : Number(this._x); }
set x(value) { this._x = value; }
additionAssignmentNumber() {
this.x += 1;
}
additionAssignmentString() {
this.x += '1';
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrString = new NumberOrString();
numberOrString.x += 1;
numberOrString.x += '1';
numberOrString.x -= 1;
numberOrString.x *= 1;
numberOrString.x /= 1;
class NumberOrObject {
constructor() {
this._x = 0;
}
get x() { return typeof this._x === 'number' ? this._x : this._x.bar; }
set x(value) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrObject = new NumberOrObject();
numberOrObject.x += 1;
numberOrObject.x -= 1;
numberOrObject.x *= 1;
numberOrObject.x /= 1;
@@ -0,0 +1,275 @@
=== tests/cases/compiler/getterSetterSubtypeAssignment.ts ===
class NumberOrUndefined {
>NumberOrUndefined : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
_x: number | undefined;
>_x : Symbol(NumberOrUndefined._x, Decl(getterSetterSubtypeAssignment.ts, 0, 25))
get x(): number { return this._x ?? 0; }
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>this._x : Symbol(NumberOrUndefined._x, Decl(getterSetterSubtypeAssignment.ts, 0, 25))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>_x : Symbol(NumberOrUndefined._x, Decl(getterSetterSubtypeAssignment.ts, 0, 25))
set x(value: number | undefined) { this._x = value; }
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 3, 10))
>this._x : Symbol(NumberOrUndefined._x, Decl(getterSetterSubtypeAssignment.ts, 0, 25))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>_x : Symbol(NumberOrUndefined._x, Decl(getterSetterSubtypeAssignment.ts, 0, 25))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 3, 10))
additionAssignment() {
>additionAssignment : Symbol(NumberOrUndefined.additionAssignment, Decl(getterSetterSubtypeAssignment.ts, 3, 57))
this.x += 1;
>this.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
}
subtractionAssignment() {
>subtractionAssignment : Symbol(NumberOrUndefined.subtractionAssignment, Decl(getterSetterSubtypeAssignment.ts, 7, 5))
this.x -= 1;
>this.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
}
multiplicationAssignment() {
>multiplicationAssignment : Symbol(NumberOrUndefined.multiplicationAssignment, Decl(getterSetterSubtypeAssignment.ts, 11, 5))
this.x *= 1;
>this.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
}
divisionAssignment() {
>divisionAssignment : Symbol(NumberOrUndefined.divisionAssignment, Decl(getterSetterSubtypeAssignment.ts, 15, 5))
this.x /= 1;
>this.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>this : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
}
}
const numberOrUndefined = new NumberOrUndefined();
>numberOrUndefined : Symbol(numberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 21, 5))
>NumberOrUndefined : Symbol(NumberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 0, 0))
numberOrUndefined.x += 1;
>numberOrUndefined.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>numberOrUndefined : Symbol(numberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 21, 5))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
numberOrUndefined.x -= 1;
>numberOrUndefined.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>numberOrUndefined : Symbol(numberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 21, 5))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
numberOrUndefined.x *= 1;
>numberOrUndefined.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>numberOrUndefined : Symbol(numberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 21, 5))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
numberOrUndefined.x /= 1;
>numberOrUndefined.x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
>numberOrUndefined : Symbol(numberOrUndefined, Decl(getterSetterSubtypeAssignment.ts, 21, 5))
>x : Symbol(NumberOrUndefined.x, Decl(getterSetterSubtypeAssignment.ts, 1, 27), Decl(getterSetterSubtypeAssignment.ts, 2, 44))
class NumberOrString {
>NumberOrString : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
_x: number | string = 0;
>_x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
get x(): number { return typeof this._x === 'number' ? this._x : Number(this._x); }
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this._x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>_x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>this._x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>_x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>this._x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>_x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
set x(value: number | string) { this._x = value; }
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 30, 10))
>this._x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>_x : Symbol(NumberOrString._x, Decl(getterSetterSubtypeAssignment.ts, 27, 22))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 30, 10))
additionAssignmentNumber() {
>additionAssignmentNumber : Symbol(NumberOrString.additionAssignmentNumber, Decl(getterSetterSubtypeAssignment.ts, 30, 54))
this.x += 1;
>this.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
}
additionAssignmentString() {
>additionAssignmentString : Symbol(NumberOrString.additionAssignmentString, Decl(getterSetterSubtypeAssignment.ts, 34, 5))
this.x += '1';
>this.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
}
subtractionAssignment() {
>subtractionAssignment : Symbol(NumberOrString.subtractionAssignment, Decl(getterSetterSubtypeAssignment.ts, 37, 5))
this.x -= 1;
>this.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
}
multiplicationAssignment() {
>multiplicationAssignment : Symbol(NumberOrString.multiplicationAssignment, Decl(getterSetterSubtypeAssignment.ts, 41, 5))
this.x *= 1;
>this.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
}
divisionAssignment() {
>divisionAssignment : Symbol(NumberOrString.divisionAssignment, Decl(getterSetterSubtypeAssignment.ts, 45, 5))
this.x /= 1;
>this.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>this : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
}
}
const numberOrString = new NumberOrString();
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>NumberOrString : Symbol(NumberOrString, Decl(getterSetterSubtypeAssignment.ts, 25, 25))
numberOrString.x += 1;
>numberOrString.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
numberOrString.x += '1';
>numberOrString.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
numberOrString.x -= 1;
>numberOrString.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
numberOrString.x *= 1;
>numberOrString.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
numberOrString.x /= 1;
>numberOrString.x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
>numberOrString : Symbol(numberOrString, Decl(getterSetterSubtypeAssignment.ts, 51, 5))
>x : Symbol(NumberOrString.x, Decl(getterSetterSubtypeAssignment.ts, 28, 28), Decl(getterSetterSubtypeAssignment.ts, 29, 87))
type Foo = { bar: number; };
>Foo : Symbol(Foo, Decl(getterSetterSubtypeAssignment.ts, 56, 22))
>bar : Symbol(bar, Decl(getterSetterSubtypeAssignment.ts, 58, 12))
class NumberOrObject {
>NumberOrObject : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
_x: number | Foo = 0;
>_x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>Foo : Symbol(Foo, Decl(getterSetterSubtypeAssignment.ts, 56, 22))
get x(): number { return typeof this._x === 'number' ? this._x : this._x.bar; }
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>this._x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>_x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this._x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>_x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this._x.bar : Symbol(bar, Decl(getterSetterSubtypeAssignment.ts, 58, 12))
>this._x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>_x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>bar : Symbol(bar, Decl(getterSetterSubtypeAssignment.ts, 58, 12))
set x(value: number | Foo) { this._x = value; }
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 62, 10))
>Foo : Symbol(Foo, Decl(getterSetterSubtypeAssignment.ts, 56, 22))
>this._x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>_x : Symbol(NumberOrObject._x, Decl(getterSetterSubtypeAssignment.ts, 59, 22))
>value : Symbol(value, Decl(getterSetterSubtypeAssignment.ts, 62, 10))
additionAssignment() {
>additionAssignment : Symbol(NumberOrObject.additionAssignment, Decl(getterSetterSubtypeAssignment.ts, 62, 51))
this.x += 1;
>this.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
}
subtractionAssignment() {
>subtractionAssignment : Symbol(NumberOrObject.subtractionAssignment, Decl(getterSetterSubtypeAssignment.ts, 66, 5))
this.x -= 1;
>this.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
}
multiplicationAssignment() {
>multiplicationAssignment : Symbol(NumberOrObject.multiplicationAssignment, Decl(getterSetterSubtypeAssignment.ts, 70, 5))
this.x *= 1;
>this.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
}
divisionAssignment() {
>divisionAssignment : Symbol(NumberOrObject.divisionAssignment, Decl(getterSetterSubtypeAssignment.ts, 74, 5))
this.x /= 1;
>this.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>this : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
}
}
const numberOrObject = new NumberOrObject();
>numberOrObject : Symbol(numberOrObject, Decl(getterSetterSubtypeAssignment.ts, 80, 5))
>NumberOrObject : Symbol(NumberOrObject, Decl(getterSetterSubtypeAssignment.ts, 58, 28))
numberOrObject.x += 1;
>numberOrObject.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>numberOrObject : Symbol(numberOrObject, Decl(getterSetterSubtypeAssignment.ts, 80, 5))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
numberOrObject.x -= 1;
>numberOrObject.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>numberOrObject : Symbol(numberOrObject, Decl(getterSetterSubtypeAssignment.ts, 80, 5))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
numberOrObject.x *= 1;
>numberOrObject.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>numberOrObject : Symbol(numberOrObject, Decl(getterSetterSubtypeAssignment.ts, 80, 5))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
numberOrObject.x /= 1;
>numberOrObject.x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
>numberOrObject : Symbol(numberOrObject, Decl(getterSetterSubtypeAssignment.ts, 80, 5))
>x : Symbol(NumberOrObject.x, Decl(getterSetterSubtypeAssignment.ts, 60, 25), Decl(getterSetterSubtypeAssignment.ts, 61, 83))
@@ -0,0 +1,344 @@
=== tests/cases/compiler/getterSetterSubtypeAssignment.ts ===
class NumberOrUndefined {
>NumberOrUndefined : NumberOrUndefined
_x: number | undefined;
>_x : number | undefined
get x(): number { return this._x ?? 0; }
>x : number
>this._x ?? 0 : number
>this._x : number | undefined
>this : this
>_x : number | undefined
>0 : 0
set x(value: number | undefined) { this._x = value; }
>x : number
>value : number | undefined
>this._x = value : number | undefined
>this._x : number | undefined
>this : this
>_x : number | undefined
>value : number | undefined
additionAssignment() {
>additionAssignment : () => void
this.x += 1;
>this.x += 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
subtractionAssignment() {
>subtractionAssignment : () => void
this.x -= 1;
>this.x -= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
multiplicationAssignment() {
>multiplicationAssignment : () => void
this.x *= 1;
>this.x *= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
divisionAssignment() {
>divisionAssignment : () => void
this.x /= 1;
>this.x /= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
}
const numberOrUndefined = new NumberOrUndefined();
>numberOrUndefined : NumberOrUndefined
>new NumberOrUndefined() : NumberOrUndefined
>NumberOrUndefined : typeof NumberOrUndefined
numberOrUndefined.x += 1;
>numberOrUndefined.x += 1 : number
>numberOrUndefined.x : number
>numberOrUndefined : NumberOrUndefined
>x : number
>1 : 1
numberOrUndefined.x -= 1;
>numberOrUndefined.x -= 1 : number
>numberOrUndefined.x : number
>numberOrUndefined : NumberOrUndefined
>x : number
>1 : 1
numberOrUndefined.x *= 1;
>numberOrUndefined.x *= 1 : number
>numberOrUndefined.x : number
>numberOrUndefined : NumberOrUndefined
>x : number
>1 : 1
numberOrUndefined.x /= 1;
>numberOrUndefined.x /= 1 : number
>numberOrUndefined.x : number
>numberOrUndefined : NumberOrUndefined
>x : number
>1 : 1
class NumberOrString {
>NumberOrString : NumberOrString
_x: number | string = 0;
>_x : string | number
>0 : 0
get x(): number { return typeof this._x === 'number' ? this._x : Number(this._x); }
>x : number
>typeof this._x === 'number' ? this._x : Number(this._x) : number
>typeof this._x === 'number' : boolean
>typeof this._x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>this._x : string | number
>this : this
>_x : string | number
>'number' : "number"
>this._x : number
>this : this
>_x : number
>Number(this._x) : number
>Number : NumberConstructor
>this._x : string
>this : this
>_x : string
set x(value: number | string) { this._x = value; }
>x : number
>value : string | number
>this._x = value : string | number
>this._x : string | number
>this : this
>_x : string | number
>value : string | number
additionAssignmentNumber() {
>additionAssignmentNumber : () => void
this.x += 1;
>this.x += 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
additionAssignmentString() {
>additionAssignmentString : () => void
this.x += '1';
>this.x += '1' : string
>this.x : number
>this : this
>x : number
>'1' : "1"
}
subtractionAssignment() {
>subtractionAssignment : () => void
this.x -= 1;
>this.x -= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
multiplicationAssignment() {
>multiplicationAssignment : () => void
this.x *= 1;
>this.x *= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
divisionAssignment() {
>divisionAssignment : () => void
this.x /= 1;
>this.x /= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
}
const numberOrString = new NumberOrString();
>numberOrString : NumberOrString
>new NumberOrString() : NumberOrString
>NumberOrString : typeof NumberOrString
numberOrString.x += 1;
>numberOrString.x += 1 : number
>numberOrString.x : number
>numberOrString : NumberOrString
>x : number
>1 : 1
numberOrString.x += '1';
>numberOrString.x += '1' : string
>numberOrString.x : number
>numberOrString : NumberOrString
>x : number
>'1' : "1"
numberOrString.x -= 1;
>numberOrString.x -= 1 : number
>numberOrString.x : number
>numberOrString : NumberOrString
>x : number
>1 : 1
numberOrString.x *= 1;
>numberOrString.x *= 1 : number
>numberOrString.x : number
>numberOrString : NumberOrString
>x : number
>1 : 1
numberOrString.x /= 1;
>numberOrString.x /= 1 : number
>numberOrString.x : number
>numberOrString : NumberOrString
>x : number
>1 : 1
type Foo = { bar: number; };
>Foo : { bar: number; }
>bar : number
class NumberOrObject {
>NumberOrObject : NumberOrObject
_x: number | Foo = 0;
>_x : number | Foo
>0 : 0
get x(): number { return typeof this._x === 'number' ? this._x : this._x.bar; }
>x : number
>typeof this._x === 'number' ? this._x : this._x.bar : number
>typeof this._x === 'number' : boolean
>typeof this._x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>this._x : number | Foo
>this : this
>_x : number | Foo
>'number' : "number"
>this._x : number
>this : this
>_x : number
>this._x.bar : number
>this._x : Foo
>this : this
>_x : Foo
>bar : number
set x(value: number | Foo) { this._x = value; }
>x : number
>value : number | Foo
>this._x = value : number | Foo
>this._x : number | Foo
>this : this
>_x : number | Foo
>value : number | Foo
additionAssignment() {
>additionAssignment : () => void
this.x += 1;
>this.x += 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
subtractionAssignment() {
>subtractionAssignment : () => void
this.x -= 1;
>this.x -= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
multiplicationAssignment() {
>multiplicationAssignment : () => void
this.x *= 1;
>this.x *= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
divisionAssignment() {
>divisionAssignment : () => void
this.x /= 1;
>this.x /= 1 : number
>this.x : number
>this : this
>x : number
>1 : 1
}
}
const numberOrObject = new NumberOrObject();
>numberOrObject : NumberOrObject
>new NumberOrObject() : NumberOrObject
>NumberOrObject : typeof NumberOrObject
numberOrObject.x += 1;
>numberOrObject.x += 1 : number
>numberOrObject.x : number
>numberOrObject : NumberOrObject
>x : number
>1 : 1
numberOrObject.x -= 1;
>numberOrObject.x -= 1 : number
>numberOrObject.x : number
>numberOrObject : NumberOrObject
>x : number
>1 : 1
numberOrObject.x *= 1;
>numberOrObject.x *= 1 : number
>numberOrObject.x : number
>numberOrObject : NumberOrObject
>x : number
>1 : 1
numberOrObject.x /= 1;
>numberOrObject.x /= 1 : number
>numberOrObject.x : number
>numberOrObject : NumberOrObject
>x : number
>1 : 1
@@ -1,5 +1,5 @@
tests/cases/compiler/noUnusedLocals_writeOnly.ts(1,12): error TS6133: 'x' is declared but its value is never read.
tests/cases/compiler/noUnusedLocals_writeOnly.ts(18,9): error TS6133: 'z' is declared but its value is never read.
tests/cases/compiler/noUnusedLocals_writeOnly.ts(16,9): error TS6133: 'z' is declared but its value is never read.
==== tests/cases/compiler/noUnusedLocals_writeOnly.ts (2 errors) ====
@@ -8,8 +8,6 @@ tests/cases/compiler/noUnusedLocals_writeOnly.ts(18,9): error TS6133: 'z' is dec
!!! error TS6133: 'x' is declared but its value is never read.
// None of these statements read from 'x', so it will be marked unused.
x = 1;
x++;
x /= 2;
([x] = [1]);
({ x } = { x: 1 });
({ x: x } = { x: 1 });
@@ -2,8 +2,6 @@
function f(x = 0, b = false) {
// None of these statements read from 'x', so it will be marked unused.
x = 1;
x++;
x /= 2;
([x] = [1]);
({ x } = { x: 1 });
({ x: x } = { x: 1 });
@@ -30,8 +28,6 @@ function f(x, b) {
if (b === void 0) { b = false; }
// None of these statements read from 'x', so it will be marked unused.
x = 1;
x++;
x /= 2;
(x = [1][0]);
(x = { x: 1 }.x);
(x = { x: 1 }.x);
@@ -8,64 +8,58 @@ function f(x = 0, b = false) {
x = 1;
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
x++;
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
x /= 2;
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
([x] = [1]);
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
({ x } = { x: 1 });
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 6, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 6, 14))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 4, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 4, 14))
({ x: x } = { x: 1 });
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 5, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 17))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 5, 17))
({ a: [{ b: x }] } = { a: [{ b: 1 }] });
>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 8, 6))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 8, 12))
>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 6, 6))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 6, 12))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11))
>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 8, 26))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 8, 32))
>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 6, 26))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 6, 32))
({ x = 2 } = { x: b ? 1 : undefined });
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 18))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 6))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 18))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 0, 17))
>undefined : Symbol(undefined)
let used = 1;
>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 10, 7))
>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 8, 7))
({ x = used } = { x: b ? 1 : undefined });
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 11, 6))
>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 10, 7))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 11, 21))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 6))
>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 8, 7))
>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 21))
>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 0, 17))
>undefined : Symbol(undefined)
let y = 0;
>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 13, 7))
>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 11, 7))
// This is a write access to y, but not a write-*only* access.
f(y++);
>f : Symbol(f, Decl(noUnusedLocals_writeOnly.ts, 0, 0))
>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 13, 7))
>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 11, 7))
let z = 0;
>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 17, 7))
>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 15, 7))
f(z = 1); // This effectively doesn't use `z`, values just pass through it.
>f : Symbol(f, Decl(noUnusedLocals_writeOnly.ts, 0, 0))
>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 17, 7))
>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 15, 7))
}
function f2(_: ReadonlyArray<number>): void {}
>f2 : Symbol(f2, Decl(noUnusedLocals_writeOnly.ts, 19, 1))
>_ : Symbol(_, Decl(noUnusedLocals_writeOnly.ts, 20, 12))
>f2 : Symbol(f2, Decl(noUnusedLocals_writeOnly.ts, 17, 1))
>_ : Symbol(_, Decl(noUnusedLocals_writeOnly.ts, 18, 12))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
@@ -12,15 +12,6 @@ function f(x = 0, b = false) {
>x : number
>1 : 1
x++;
>x++ : number
>x : number
x /= 2;
>x /= 2 : number
>x : number
>2 : 2
([x] = [1]);
>([x] = [1]) : [number]
>[x] = [1] : [number]
@@ -7,6 +7,5 @@ tests/cases/compiler/unusedLocalsInMethod2.ts(3,9): error TS6199: All variables
var x, y = 10;
~~~~~~~~~~~~~~
!!! error TS6199: All variables are unused.
y++;
}
}
@@ -2,7 +2,6 @@
class greeter {
public function1() {
var x, y = 10;
y++;
}
}
@@ -12,7 +11,6 @@ var greeter = /** @class */ (function () {
}
greeter.prototype.function1 = function () {
var x, y = 10;
y++;
};
return greeter;
}());
@@ -7,9 +7,6 @@ class greeter {
var x, y = 10;
>x : Symbol(x, Decl(unusedLocalsInMethod2.ts, 2, 11))
>y : Symbol(y, Decl(unusedLocalsInMethod2.ts, 2, 14))
y++;
>y : Symbol(y, Decl(unusedLocalsInMethod2.ts, 2, 14))
}
}
@@ -9,9 +9,5 @@ class greeter {
>x : any
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
}
@@ -10,7 +10,6 @@ tests/cases/compiler/unusedParameterProperty1.ts(3,13): error TS6133: 'foge' is
let foge = used;
~~~~
!!! error TS6133: 'foge' is declared but its value is never read.
foge += "";
}
}
@@ -2,7 +2,6 @@
class A {
constructor(private used: string) {
let foge = used;
foge += "";
}
}
@@ -12,7 +11,6 @@ var A = /** @class */ (function () {
function A(used) {
this.used = used;
var foge = used;
foge += "";
}
return A;
}());
@@ -8,9 +8,6 @@ class A {
let foge = used;
>foge : Symbol(foge, Decl(unusedParameterProperty1.ts, 2, 11))
>used : Symbol(used, Decl(unusedParameterProperty1.ts, 1, 16))
foge += "";
>foge : Symbol(foge, Decl(unusedParameterProperty1.ts, 2, 11))
}
}
@@ -8,11 +8,6 @@ class A {
let foge = used;
>foge : string
>used : string
foge += "";
>foge += "" : string
>foge : string
>"" : ""
}
}
@@ -10,7 +10,6 @@ tests/cases/compiler/unusedParameterProperty2.ts(3,13): error TS6133: 'foge' is
let foge = used;
~~~~
!!! error TS6133: 'foge' is declared but its value is never read.
foge += "";
}
}
@@ -2,7 +2,6 @@
class A {
constructor(private used) {
let foge = used;
foge += "";
}
}
@@ -12,7 +11,6 @@ var A = /** @class */ (function () {
function A(used) {
this.used = used;
var foge = used;
foge += "";
}
return A;
}());
@@ -8,9 +8,6 @@ class A {
let foge = used;
>foge : Symbol(foge, Decl(unusedParameterProperty2.ts, 2, 11))
>used : Symbol(used, Decl(unusedParameterProperty2.ts, 1, 16))
foge += "";
>foge : Symbol(foge, Decl(unusedParameterProperty2.ts, 2, 11))
}
}
@@ -8,11 +8,6 @@ class A {
let foge = used;
>foge : any
>used : any
foge += "";
>foge += "" : string
>foge : any
>"" : ""
}
}
@@ -64,7 +64,6 @@ tests/cases/compiler/unusedPrivateMembers.ts(56,13): error TS6133: 'b' is declar
public test() {
var x = new Test6();
x.a++;
x.b++;
}
}
@@ -59,7 +59,6 @@ class Test6 {
public test() {
var x = new Test6();
x.a++;
x.b++;
}
}
@@ -144,7 +143,6 @@ var Test6 = /** @class */ (function () {
Test6.prototype.test = function () {
var x = new Test6();
x.a++;
x.b++;
};
return Test6;
}());
@@ -139,11 +139,6 @@ class Test6 {
>x.a : Symbol(Test6.a, Decl(unusedPrivateMembers.ts, 48, 13), Decl(unusedPrivateMembers.ts, 51, 5))
>x : Symbol(x, Decl(unusedPrivateMembers.ts, 58, 11))
>a : Symbol(Test6.a, Decl(unusedPrivateMembers.ts, 48, 13), Decl(unusedPrivateMembers.ts, 51, 5))
x.b++;
>x.b : Symbol(Test6.b, Decl(unusedPrivateMembers.ts, 54, 5))
>x : Symbol(x, Decl(unusedPrivateMembers.ts, 58, 11))
>b : Symbol(Test6.b, Decl(unusedPrivateMembers.ts, 54, 5))
}
}
@@ -149,12 +149,6 @@ class Test6 {
>x.a : number
>x : Test6
>a : number
x.b++;
>x.b++ : number
>x.b : number
>x : Test6
>b : number
}
}
@@ -10,6 +10,5 @@ tests/cases/compiler/unusedPrivateMethodInClass1.ts(3,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
}
@@ -2,7 +2,6 @@
class greeter {
private function1() {
var y = 10;
y++;
}
}
@@ -12,7 +11,6 @@ var greeter = /** @class */ (function () {
}
greeter.prototype.function1 = function () {
var y = 10;
y++;
};
return greeter;
}());
@@ -7,8 +7,5 @@ class greeter {
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass1.ts, 2, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass1.ts, 2, 11))
}
}
@@ -8,9 +8,5 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
}
@@ -1,7 +1,7 @@
tests/cases/compiler/unusedPrivateMethodInClass2.ts(2,13): error TS6133: 'function1' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass2.ts(3,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass2.ts(7,13): error TS6133: 'function2' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass2.ts(8,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass2.ts(6,13): error TS6133: 'function2' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass2.ts(7,13): error TS6133: 'y' is declared but its value is never read.
==== tests/cases/compiler/unusedPrivateMethodInClass2.ts (4 errors) ====
@@ -12,7 +12,6 @@ tests/cases/compiler/unusedPrivateMethodInClass2.ts(8,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
private function2() {
@@ -21,6 +20,5 @@ tests/cases/compiler/unusedPrivateMethodInClass2.ts(8,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
}
@@ -2,12 +2,10 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
}
@@ -17,11 +15,9 @@ var greeter = /** @class */ (function () {
}
greeter.prototype.function1 = function () {
var y = 10;
y++;
};
greeter.prototype.function2 = function () {
var y = 10;
y++;
};
return greeter;
}());
@@ -7,18 +7,12 @@ class greeter {
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass2.ts, 2, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass2.ts, 2, 11))
}
private function2() {
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass2.ts, 4, 5))
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass2.ts, 3, 5))
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass2.ts, 7, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass2.ts, 7, 11))
>y : Symbol(y, Decl(unusedPrivateMethodInClass2.ts, 6, 11))
}
}
@@ -8,10 +8,6 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
private function2() {
@@ -20,9 +16,5 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
}
@@ -1,8 +1,8 @@
tests/cases/compiler/unusedPrivateMethodInClass3.ts(2,13): error TS6133: 'function1' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(3,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(7,13): error TS6133: 'function2' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(8,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(13,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(6,13): error TS6133: 'function2' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(7,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass3.ts(11,13): error TS6133: 'y' is declared but its value is never read.
==== tests/cases/compiler/unusedPrivateMethodInClass3.ts (5 errors) ====
@@ -13,7 +13,6 @@ tests/cases/compiler/unusedPrivateMethodInClass3.ts(13,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
private function2() {
@@ -22,13 +21,11 @@ tests/cases/compiler/unusedPrivateMethodInClass3.ts(13,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
public function3() {
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
}
@@ -2,17 +2,14 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
public function3() {
var y = 10;
y++;
}
}
@@ -22,15 +19,12 @@ var greeter = /** @class */ (function () {
}
greeter.prototype.function1 = function () {
var y = 10;
y++;
};
greeter.prototype.function2 = function () {
var y = 10;
y++;
};
greeter.prototype.function3 = function () {
var y = 10;
y++;
};
return greeter;
}());
@@ -7,28 +7,19 @@ class greeter {
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 2, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 2, 11))
}
private function2() {
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass3.ts, 4, 5))
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass3.ts, 3, 5))
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 7, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 7, 11))
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 6, 11))
}
public function3() {
>function3 : Symbol(greeter.function3, Decl(unusedPrivateMethodInClass3.ts, 9, 5))
>function3 : Symbol(greeter.function3, Decl(unusedPrivateMethodInClass3.ts, 7, 5))
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 12, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 12, 11))
>y : Symbol(y, Decl(unusedPrivateMethodInClass3.ts, 10, 11))
}
}
@@ -8,10 +8,6 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
private function2() {
@@ -20,10 +16,6 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
public function3() {
@@ -32,9 +24,5 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
}
@@ -1,7 +1,7 @@
tests/cases/compiler/unusedPrivateMethodInClass4.ts(2,13): error TS6133: 'function1' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass4.ts(3,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass4.ts(8,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass4.ts(13,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass4.ts(7,13): error TS6133: 'y' is declared but its value is never read.
tests/cases/compiler/unusedPrivateMethodInClass4.ts(11,13): error TS6133: 'y' is declared but its value is never read.
==== tests/cases/compiler/unusedPrivateMethodInClass4.ts (4 errors) ====
@@ -12,21 +12,18 @@ tests/cases/compiler/unusedPrivateMethodInClass4.ts(13,13): error TS6133: 'y' is
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
private function2() {
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
}
public function3() {
var y = 10;
~
!!! error TS6133: 'y' is declared but its value is never read.
y++;
this.function2();
}
}
@@ -2,17 +2,14 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
public function3() {
var y = 10;
y++;
this.function2();
}
}
@@ -23,15 +20,12 @@ var greeter = /** @class */ (function () {
}
greeter.prototype.function1 = function () {
var y = 10;
y++;
};
greeter.prototype.function2 = function () {
var y = 10;
y++;
};
greeter.prototype.function3 = function () {
var y = 10;
y++;
this.function2();
};
return greeter;
@@ -7,33 +7,24 @@ class greeter {
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 2, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 2, 11))
}
private function2() {
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 4, 5))
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 3, 5))
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 7, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 7, 11))
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 6, 11))
}
public function3() {
>function3 : Symbol(greeter.function3, Decl(unusedPrivateMethodInClass4.ts, 9, 5))
>function3 : Symbol(greeter.function3, Decl(unusedPrivateMethodInClass4.ts, 7, 5))
var y = 10;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 12, 11))
y++;
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 12, 11))
>y : Symbol(y, Decl(unusedPrivateMethodInClass4.ts, 10, 11))
this.function2();
>this.function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 4, 5))
>this.function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 3, 5))
>this : Symbol(greeter, Decl(unusedPrivateMethodInClass4.ts, 0, 0))
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 4, 5))
>function2 : Symbol(greeter.function2, Decl(unusedPrivateMethodInClass4.ts, 3, 5))
}
}
@@ -8,10 +8,6 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
private function2() {
@@ -20,10 +16,6 @@ class greeter {
var y = 10;
>y : number
>10 : 10
y++;
>y++ : number
>y : number
}
public function3() {
@@ -33,10 +25,6 @@ class greeter {
>y : number
>10 : 10
y++;
>y++ : number
>y : number
this.function2();
>this.function2() : void
>this.function2 : () => void
@@ -38,5 +38,5 @@ tests/cases/compiler/unusedSwitchStatement.ts(16,10): error TS2678: Type '1' is
case 1:
~
!!! error TS2678: Type '1' is not comparable to type '2'.
x++;
x=1;
}
@@ -15,7 +15,7 @@ switch (2) {
case 0:
let x;
case 1:
x++;
x=1;
}
//// [unusedSwitchStatement.js]
@@ -33,5 +33,5 @@ switch (2) {
case 0:
var x = void 0;
case 1:
x++;
x = 1;
}
@@ -22,6 +22,6 @@ switch (2) {
>x : Symbol(x, Decl(unusedSwitchStatement.ts, 14, 11))
case 1:
x++;
x=1;
>x : Symbol(x, Decl(unusedSwitchStatement.ts, 14, 11))
}
@@ -36,7 +36,8 @@ switch (2) {
case 1:
>1 : 1
x++;
>x++ : number
x=1;
>x=1 : 1
>x : any
>1 : 1
}
@@ -11,6 +11,5 @@ tests/cases/compiler/unusedVariablesinBlocks1.ts(4,13): error TS6133: 'x' is dec
let x = 11;
~
!!! error TS6133: 'x' is declared but its value is never read.
x++;
}
}
@@ -3,7 +3,6 @@ function f1 () {
let x = 10;
{
let x = 11;
x++;
}
}
@@ -12,6 +11,5 @@ function f1() {
var x = 10;
{
var x_1 = 11;
x_1++;
}
}
@@ -7,8 +7,5 @@ function f1 () {
{
let x = 11;
>x : Symbol(x, Decl(unusedVariablesinBlocks1.ts, 3, 11))
x++;
>x : Symbol(x, Decl(unusedVariablesinBlocks1.ts, 3, 11))
}
}
@@ -9,9 +9,5 @@ function f1 () {
let x = 11;
>x : number
>11 : 11
x++;
>x++ : number
>x : number
}
}
@@ -12,5 +12,4 @@ tests/cases/compiler/unusedVariablesinBlocks2.ts(4,13): error TS6133: 'x' is dec
~
!!! error TS6133: 'x' is declared but its value is never read.
}
x++;
}
@@ -4,7 +4,6 @@ function f1 () {
{
let x = 11;
}
x++;
}
//// [unusedVariablesinBlocks2.js]
@@ -13,5 +12,4 @@ function f1() {
{
var x_1 = 11;
}
x++;
}
@@ -8,6 +8,4 @@ function f1 () {
let x = 11;
>x : Symbol(x, Decl(unusedVariablesinBlocks2.ts, 3, 11))
}
x++;
>x : Symbol(x, Decl(unusedVariablesinBlocks2.ts, 1, 7))
}
@@ -10,7 +10,4 @@ function f1 () {
>x : number
>11 : 11
}
x++;
>x++ : number
>x : number
}
@@ -0,0 +1,89 @@
// @target: es2015
// @strictNullChecks: true
// @noImplicitThis: true
class NumberOrUndefined {
_x: number | undefined;
get x(): number { return this._x ?? 0; }
set x(value: number | undefined) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrUndefined = new NumberOrUndefined();
numberOrUndefined.x += 1;
numberOrUndefined.x -= 1;
numberOrUndefined.x *= 1;
numberOrUndefined.x /= 1;
class NumberOrString {
_x: number | string = 0;
get x(): number { return typeof this._x === 'number' ? this._x : Number(this._x); }
set x(value: number | string) { this._x = value; }
additionAssignmentNumber() {
this.x += 1;
}
additionAssignmentString() {
this.x += '1';
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrString = new NumberOrString();
numberOrString.x += 1;
numberOrString.x += '1';
numberOrString.x -= 1;
numberOrString.x *= 1;
numberOrString.x /= 1;
type Foo = { bar: number; };
class NumberOrObject {
_x: number | Foo = 0;
get x(): number { return typeof this._x === 'number' ? this._x : this._x.bar; }
set x(value: number | Foo) { this._x = value; }
additionAssignment() {
this.x += 1;
}
subtractionAssignment() {
this.x -= 1;
}
multiplicationAssignment() {
this.x *= 1;
}
divisionAssignment() {
this.x /= 1;
}
}
const numberOrObject = new NumberOrObject();
numberOrObject.x += 1;
numberOrObject.x -= 1;
numberOrObject.x *= 1;
numberOrObject.x /= 1;
@@ -5,8 +5,6 @@
function f(x = 0, b = false) {
// None of these statements read from 'x', so it will be marked unused.
x = 1;
x++;
x /= 2;
([x] = [1]);
({ x } = { x: 1 });
({ x: x } = { x: 1 });
@@ -4,6 +4,5 @@
class greeter {
public function1() {
var x, y = 10;
y++;
}
}
@@ -4,6 +4,5 @@
class A {
constructor(private used: string) {
let foge = used;
foge += "";
}
}
@@ -4,6 +4,5 @@
class A {
constructor(private used) {
let foge = used;
foge += "";
}
}
@@ -62,6 +62,5 @@ class Test6 {
public test() {
var x = new Test6();
x.a++;
x.b++;
}
}
@@ -4,6 +4,5 @@
class greeter {
private function1() {
var y = 10;
y++;
}
}
@@ -4,11 +4,9 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
}
@@ -4,16 +4,13 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
public function3() {
var y = 10;
y++;
}
}
@@ -4,17 +4,14 @@
class greeter {
private function1() {
var y = 10;
y++;
}
private function2() {
var y = 10;
y++;
}
public function3() {
var y = 10;
y++;
this.function2();
}
}
@@ -17,5 +17,5 @@ switch (2) {
case 0:
let x;
case 1:
x++;
x=1;
}
@@ -5,6 +5,5 @@ function f1 () {
let x = 10;
{
let x = 11;
x++;
}
}
@@ -6,5 +6,4 @@ function f1 () {
{
let x = 11;
}
x++;
}
@@ -1,14 +0,0 @@
/// <reference path='fourslash.ts' />
// @noUnusedLocals: true
////function fn() {
//// let x = 1;
//// x++;
////}
verify.codeFix({
description: "Remove unused declaration for: 'x'",
newFileContent:
`function fn() {
}`
});
@@ -1,14 +0,0 @@
/// <reference path='fourslash.ts' />
// @noUnusedLocals: true
////function fn() {
//// let x = 1;
//// x--;
////}
verify.codeFix({
description: "Remove unused declaration for: 'x'",
newFileContent:
`function fn() {
}`
});
@@ -1,14 +0,0 @@
/// <reference path='fourslash.ts' />
// @noUnusedLocals: true
////function fn() {
//// let x = 1;
//// ++x;
////}
verify.codeFix({
description: "Remove unused declaration for: 'x'",
newFileContent:
`function fn() {
}`
});
@@ -1,14 +0,0 @@
/// <reference path='fourslash.ts' />
// @noUnusedLocals: true
////function fn() {
//// let x = 1;
//// --x;
////}
verify.codeFix({
description: "Remove unused declaration for: 'x'",
newFileContent:
`function fn() {
}`
});