Abstract property access error only on this access
This commit is contained in:
parent
fb45b49afc
commit
49beac919c
|
@ -14907,7 +14907,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Referencing abstract properties within their own constructors is not allowed
|
||||
if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop)) {
|
||||
if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) {
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
|
||||
if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) {
|
||||
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name));
|
||||
|
|
|
@ -1121,7 +1121,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for super.
|
||||
* Determines whether a node is a property or element access expression for `super`.
|
||||
*/
|
||||
export function isSuperProperty(node: Node): node is SuperProperty {
|
||||
const kind = node.kind;
|
||||
|
@ -1129,7 +1129,16 @@ namespace ts {
|
|||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for `this`.
|
||||
*/
|
||||
export function isThisProperty(node: Node): boolean {
|
||||
const kind = node.kind;
|
||||
return (kind === SyntaxKind.PropertyAccessExpression || kind === SyntaxKind.ElementAccessExpression)
|
||||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.ThisKeyword;
|
||||
}
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
|
|
|
@ -5,7 +5,7 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstr
|
|||
|
||||
==== tests/cases/compiler/abstractPropertyInConstructor.ts (3 errors) ====
|
||||
abstract class AbstractClass {
|
||||
constructor(str: string) {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
this.method(parseInt(str));
|
||||
let val = this.prop.toLowerCase();
|
||||
~~~~
|
||||
|
@ -20,9 +20,13 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstr
|
|||
~~
|
||||
!!! error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
|
||||
// OK, reference is inside function
|
||||
const innerFunction = () => {
|
||||
return this.prop;
|
||||
}
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
}
|
||||
|
||||
abstract prop: string;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//// [abstractPropertyInConstructor.ts]
|
||||
abstract class AbstractClass {
|
||||
constructor(str: string) {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
this.method(parseInt(str));
|
||||
let val = this.prop.toLowerCase();
|
||||
|
||||
|
@ -9,9 +9,13 @@ abstract class AbstractClass {
|
|||
}
|
||||
this.cb(str);
|
||||
|
||||
// OK, reference is inside function
|
||||
const innerFunction = () => {
|
||||
return this.prop;
|
||||
}
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
}
|
||||
|
||||
abstract prop: string;
|
||||
|
@ -36,7 +40,7 @@ class User {
|
|||
|
||||
//// [abstractPropertyInConstructor.js]
|
||||
var AbstractClass = /** @class */ (function () {
|
||||
function AbstractClass(str) {
|
||||
function AbstractClass(str, other) {
|
||||
var _this = this;
|
||||
this.method(parseInt(str));
|
||||
var val = this.prop.toLowerCase();
|
||||
|
@ -44,9 +48,12 @@ var AbstractClass = /** @class */ (function () {
|
|||
this.prop = "Hello World";
|
||||
}
|
||||
this.cb(str);
|
||||
// OK, reference is inside function
|
||||
var innerFunction = function () {
|
||||
return _this.prop;
|
||||
};
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
}
|
||||
AbstractClass.prototype.method2 = function () {
|
||||
this.prop = this.prop + "!";
|
||||
|
|
|
@ -2,98 +2,110 @@
|
|||
abstract class AbstractClass {
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
|
||||
constructor(str: string) {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
|
||||
this.method(parseInt(str));
|
||||
>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37))
|
||||
>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>parseInt : Symbol(parseInt, Decl(lib.d.ts, --, --))
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16))
|
||||
|
||||
let val = this.prop.toLowerCase();
|
||||
>val : Symbol(val, Decl(abstractPropertyInConstructor.ts, 3, 11))
|
||||
>this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
|
||||
if (!str) {
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16))
|
||||
|
||||
this.prop = "Hello World";
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
}
|
||||
this.cb(str);
|
||||
>this.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26))
|
||||
>this.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16))
|
||||
|
||||
// OK, reference is inside function
|
||||
const innerFunction = () => {
|
||||
>innerFunction : Symbol(innerFunction, Decl(abstractPropertyInConstructor.ts, 10, 13))
|
||||
>innerFunction : Symbol(innerFunction, Decl(abstractPropertyInConstructor.ts, 11, 13))
|
||||
|
||||
return this.prop;
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
}
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
>other.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>other.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
}
|
||||
|
||||
abstract prop: string;
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
|
||||
abstract cb: (s: string) => void;
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26))
|
||||
>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 16, 18))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 20, 18))
|
||||
|
||||
abstract method(num: number): void;
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37))
|
||||
>num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 18, 20))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 22, 20))
|
||||
|
||||
method2() {
|
||||
>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39))
|
||||
>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39))
|
||||
|
||||
this.prop = this.prop + "!";
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 23, 1))
|
||||
>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 27, 1))
|
||||
|
||||
constructor(a: AbstractClass) {
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
|
||||
a.prop;
|
||||
>a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5))
|
||||
>a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
|
||||
a.cb("hi");
|
||||
>a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26))
|
||||
>a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
|
||||
a.method(12);
|
||||
>a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37))
|
||||
>a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
|
||||
a.method2();
|
||||
>a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16))
|
||||
>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39))
|
||||
>a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16))
|
||||
>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
abstract class AbstractClass {
|
||||
>AbstractClass : AbstractClass
|
||||
|
||||
constructor(str: string) {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
>str : string
|
||||
>other : AbstractClass
|
||||
>AbstractClass : AbstractClass
|
||||
|
||||
this.method(parseInt(str));
|
||||
>this.method(parseInt(str)) : void
|
||||
|
@ -41,6 +43,7 @@ abstract class AbstractClass {
|
|||
>cb : (s: string) => void
|
||||
>str : string
|
||||
|
||||
// OK, reference is inside function
|
||||
const innerFunction = () => {
|
||||
>innerFunction : () => string
|
||||
>() => { return this.prop; } : () => string
|
||||
|
@ -50,6 +53,16 @@ abstract class AbstractClass {
|
|||
>this : this
|
||||
>prop : string
|
||||
}
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
>other.cb(other.prop) : void
|
||||
>other.cb : (s: string) => void
|
||||
>other : AbstractClass
|
||||
>cb : (s: string) => void
|
||||
>other.prop : string
|
||||
>other : AbstractClass
|
||||
>prop : string
|
||||
}
|
||||
|
||||
abstract prop: string;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
abstract class AbstractClass {
|
||||
constructor(str: string) {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
this.method(parseInt(str));
|
||||
let val = this.prop.toLowerCase();
|
||||
|
||||
|
@ -8,9 +8,13 @@ abstract class AbstractClass {
|
|||
}
|
||||
this.cb(str);
|
||||
|
||||
// OK, reference is inside function
|
||||
const innerFunction = () => {
|
||||
return this.prop;
|
||||
}
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
}
|
||||
|
||||
abstract prop: string;
|
||||
|
|
Loading…
Reference in a new issue