Avoid circular reference in this-property assignments (#37827)

* Avoid circular reference in this-property assignments

To do this, don't check this-property assigments that have the
this-property of the lhs appearing somewhere on the rhs:

```js
class C {
  m() {
    this.x = 12
    this.x = this.x + this.y
  }
}
```

I tried suppressing the circularity error, but because we cache the
first type discovered for a property, this still results in an implicit
any for `x` in the previous example. It just doesn't have an error.

Fixes #35099

* Add test case + rename function

* Use isMatchingReference
This commit is contained in:
Nathan Shively-Sanders
2020-04-10 16:41:31 -07:00
committed by GitHub
parent 795a5c83fe
commit eb105efdcd
5 changed files with 172 additions and 0 deletions

View File

@@ -7635,6 +7635,9 @@ namespace ts {
}
return anyType;
}
if (containsSameNamedThisProperty(expression.left, expression.right)) {
return anyType;
}
const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : getWidenedLiteralType(checkExpressionCached(expression.right));
if (type.flags & TypeFlags.Object &&
kind === AssignmentDeclarationKind.ModuleExports &&
@@ -7673,6 +7676,12 @@ namespace ts {
return type;
}
function containsSameNamedThisProperty(thisProperty: Expression, expression: Expression) {
return isPropertyAccessExpression(thisProperty)
&& thisProperty.expression.kind === SyntaxKind.ThisKeyword
&& forEachChildRecursively(expression, n => isMatchingReference(thisProperty, n));
}
function isDeclarationInConstructor(expression: Expression) {
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
// Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added.