Skip to content

Commit f00d00b

Browse files
committed
Allow protected members to be accessed within the enclosing class
1 parent 8230bc6 commit f00d00b

File tree

4 files changed

+230
-1
lines changed

4 files changed

+230
-1
lines changed

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33868,7 +33868,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3386833868
// get the original type -- represented as the type constraint of the 'this' type
3386933869
containingType = (containingType as TypeParameter).isThisType ? getConstraintOfTypeParameter(containingType as TypeParameter)! : getBaseConstraintOfType(containingType as TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined
3387033870
}
33871-
if (!containingType || !hasBaseType(containingType, enclosingClass)) {
33871+
if (!containingType || !hasBaseType(containingType, enclosingClass) && !isNodeWithinClass(location, getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!)) {
3387233872
if (errorNode) {
3387333873
error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2, symbolToString(prop), typeToString(enclosingClass), typeToString(containingType));
3387433874
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//// [tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass2.ts] ////
2+
3+
=== protectedClassPropertyAccessibleWithinNestedSubclass2.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/59989
5+
6+
export class Foo {
7+
>Foo : Symbol(Foo, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 0, 0))
8+
9+
protected thisIsProtected = 1;
10+
>thisIsProtected : Symbol(Foo.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 2, 18))
11+
12+
private thisIsPrivate = 1;
13+
>thisIsPrivate : Symbol(Foo.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 3, 32))
14+
15+
bar(): Foo {
16+
>bar : Symbol(Foo.bar, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 4, 28))
17+
>Foo : Symbol(Foo, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 0, 0))
18+
19+
const that = this;
20+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 7, 9))
21+
>this : Symbol(Foo, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 0, 0))
22+
23+
return new (class extends Foo {
24+
>Foo : Symbol(Foo, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 0, 0))
25+
26+
something() {
27+
>something : Symbol((Anonymous class).something, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 9, 35))
28+
29+
return that.thisIsPrivate + that.thisIsProtected; // ok
30+
>that.thisIsPrivate : Symbol(Foo.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 3, 32))
31+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 7, 9))
32+
>thisIsPrivate : Symbol(Foo.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 3, 32))
33+
>that.thisIsProtected : Symbol(Foo.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 2, 18))
34+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 7, 9))
35+
>thisIsProtected : Symbol(Foo.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 2, 18))
36+
}
37+
})();
38+
}
39+
}
40+
41+
export class Foo2 {
42+
>Foo2 : Symbol(Foo2, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 15, 1))
43+
44+
protected thisIsProtected = 1;
45+
>thisIsProtected : Symbol(Foo2.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 17, 19))
46+
47+
private thisIsPrivate = 1;
48+
>thisIsPrivate : Symbol(Foo2.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 18, 32))
49+
50+
bar() {
51+
>bar : Symbol(Foo2.bar, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 19, 28))
52+
53+
const that = this;
54+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 22, 9))
55+
>this : Symbol(Foo2, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 15, 1))
56+
57+
return new (class {
58+
something() {
59+
>something : Symbol((Anonymous class).something, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 24, 23))
60+
61+
return that.thisIsPrivate + that.thisIsProtected; // ok
62+
>that.thisIsPrivate : Symbol(Foo2.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 18, 32))
63+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 22, 9))
64+
>thisIsPrivate : Symbol(Foo2.thisIsPrivate, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 18, 32))
65+
>that.thisIsProtected : Symbol(Foo2.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 17, 19))
66+
>that : Symbol(that, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 22, 9))
67+
>thisIsProtected : Symbol(Foo2.thisIsProtected, Decl(protectedClassPropertyAccessibleWithinNestedSubclass2.ts, 17, 19))
68+
}
69+
})();
70+
}
71+
}
72+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//// [tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass2.ts] ////
2+
3+
=== protectedClassPropertyAccessibleWithinNestedSubclass2.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/59989
5+
6+
export class Foo {
7+
>Foo : Foo
8+
> : ^^^
9+
10+
protected thisIsProtected = 1;
11+
>thisIsProtected : number
12+
> : ^^^^^^
13+
>1 : 1
14+
> : ^
15+
16+
private thisIsPrivate = 1;
17+
>thisIsPrivate : number
18+
> : ^^^^^^
19+
>1 : 1
20+
> : ^
21+
22+
bar(): Foo {
23+
>bar : () => Foo
24+
> : ^^^^^^
25+
26+
const that = this;
27+
>that : this
28+
> : ^^^^
29+
>this : this
30+
> : ^^^^
31+
32+
return new (class extends Foo {
33+
>new (class extends Foo { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } })() : (Anonymous class)
34+
> : ^^^^^^^^^^^^^^^^^
35+
>(class extends Foo { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } }) : typeof (Anonymous class)
36+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
37+
>class extends Foo { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } } : typeof (Anonymous class)
38+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
39+
>Foo : Foo
40+
> : ^^^
41+
42+
something() {
43+
>something : () => number
44+
> : ^^^^^^^^^^^^
45+
46+
return that.thisIsPrivate + that.thisIsProtected; // ok
47+
>that.thisIsPrivate + that.thisIsProtected : number
48+
> : ^^^^^^
49+
>that.thisIsPrivate : number
50+
> : ^^^^^^
51+
>that : this
52+
> : ^^^^
53+
>thisIsPrivate : number
54+
> : ^^^^^^
55+
>that.thisIsProtected : number
56+
> : ^^^^^^
57+
>that : this
58+
> : ^^^^
59+
>thisIsProtected : number
60+
> : ^^^^^^
61+
}
62+
})();
63+
}
64+
}
65+
66+
export class Foo2 {
67+
>Foo2 : Foo2
68+
> : ^^^^
69+
70+
protected thisIsProtected = 1;
71+
>thisIsProtected : number
72+
> : ^^^^^^
73+
>1 : 1
74+
> : ^
75+
76+
private thisIsPrivate = 1;
77+
>thisIsPrivate : number
78+
> : ^^^^^^
79+
>1 : 1
80+
> : ^
81+
82+
bar() {
83+
>bar : () => (Anonymous class)
84+
> : ^^^^^^^^^^^^^^^^^^^^^^^
85+
86+
const that = this;
87+
>that : this
88+
> : ^^^^
89+
>this : this
90+
> : ^^^^
91+
92+
return new (class {
93+
>new (class { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } })() : (Anonymous class)
94+
> : ^^^^^^^^^^^^^^^^^
95+
>(class { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } }) : typeof (Anonymous class)
96+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
97+
>class { something() { return that.thisIsPrivate + that.thisIsProtected; // ok } } : typeof (Anonymous class)
98+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
99+
100+
something() {
101+
>something : () => number
102+
> : ^^^^^^^^^^^^
103+
104+
return that.thisIsPrivate + that.thisIsProtected; // ok
105+
>that.thisIsPrivate + that.thisIsProtected : number
106+
> : ^^^^^^
107+
>that.thisIsPrivate : number
108+
> : ^^^^^^
109+
>that : this
110+
> : ^^^^
111+
>thisIsPrivate : number
112+
> : ^^^^^^
113+
>that.thisIsProtected : number
114+
> : ^^^^^^
115+
>that : this
116+
> : ^^^^
117+
>thisIsProtected : number
118+
> : ^^^^^^
119+
}
120+
})();
121+
}
122+
}
123+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/59989
5+
6+
export class Foo {
7+
protected thisIsProtected = 1;
8+
private thisIsPrivate = 1;
9+
10+
bar(): Foo {
11+
const that = this;
12+
13+
return new (class extends Foo {
14+
something() {
15+
return that.thisIsPrivate + that.thisIsProtected; // ok
16+
}
17+
})();
18+
}
19+
}
20+
21+
export class Foo2 {
22+
protected thisIsProtected = 1;
23+
private thisIsPrivate = 1;
24+
25+
bar() {
26+
const that = this;
27+
28+
return new (class {
29+
something() {
30+
return that.thisIsPrivate + that.thisIsProtected; // ok
31+
}
32+
})();
33+
}
34+
}

0 commit comments

Comments
 (0)