diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 77f35376da7..75be3647422 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -710,6 +710,7 @@ import { isPrivateIdentifier, isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression, + isPrivateIdentifierSymbol, isPropertyAccessEntityNameExpression, isPropertyAccessExpression, isPropertyAccessOrQualifiedName, @@ -7610,6 +7611,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); } + if (isPrivateIdentifierSymbol(propertySymbol) && context.tracker.reportPrivateInBaseOfClassExpression) { + context.tracker.reportPrivateInBaseOfClassExpression(idText((propertySymbol.valueDeclaration! as NamedDeclaration).name! as PrivateIdentifier)); + } } if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) { context.out.truncated = true; diff --git a/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.errors.txt b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.errors.txt new file mode 100644 index 00000000000..c5c1abb1bc2 --- /dev/null +++ b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.errors.txt @@ -0,0 +1,31 @@ +privateFieldsInClassExpressionDeclaration.ts(1,14): error TS4094: Property '#context' of exported anonymous class type may not be private or protected. +privateFieldsInClassExpressionDeclaration.ts(1,14): error TS4094: Property '#method' of exported anonymous class type may not be private or protected. +privateFieldsInClassExpressionDeclaration.ts(8,14): error TS4094: Property '#instancePrivate' of exported anonymous class type may not be private or protected. +privateFieldsInClassExpressionDeclaration.ts(8,14): error TS4094: Property '#staticPrivate' of exported anonymous class type may not be private or protected. + + +==== privateFieldsInClassExpressionDeclaration.ts (4 errors) ==== + export const ClassExpression = class { + ~~~~~~~~~~~~~~~ +!!! error TS4094: Property '#context' of exported anonymous class type may not be private or protected. +!!! related TS9027 privateFieldsInClassExpressionDeclaration.ts:1:14: Add a type annotation to the variable ClassExpression. + ~~~~~~~~~~~~~~~ +!!! error TS4094: Property '#method' of exported anonymous class type may not be private or protected. +!!! related TS9027 privateFieldsInClassExpressionDeclaration.ts:1:14: Add a type annotation to the variable ClassExpression. + #context = 0; + #method() { return 42; } + public value = 1; + }; + + // Additional test with static private fields + export const ClassExpressionStatic = class { + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4094: Property '#instancePrivate' of exported anonymous class type may not be private or protected. +!!! related TS9027 privateFieldsInClassExpressionDeclaration.ts:8:14: Add a type annotation to the variable ClassExpressionStatic. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4094: Property '#staticPrivate' of exported anonymous class type may not be private or protected. +!!! related TS9027 privateFieldsInClassExpressionDeclaration.ts:8:14: Add a type annotation to the variable ClassExpressionStatic. + static #staticPrivate = "hidden"; + #instancePrivate = true; + public exposed = "visible"; + }; \ No newline at end of file diff --git a/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.js b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.js new file mode 100644 index 00000000000..c801596e5ff --- /dev/null +++ b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.js @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts] //// + +//// [privateFieldsInClassExpressionDeclaration.ts] +export const ClassExpression = class { + #context = 0; + #method() { return 42; } + public value = 1; +}; + +// Additional test with static private fields +export const ClassExpressionStatic = class { + static #staticPrivate = "hidden"; + #instancePrivate = true; + public exposed = "visible"; +}; + +//// [privateFieldsInClassExpressionDeclaration.js] +var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); +}; +var _instances, _context, _method, _a, _b, _ClassExpressionStatic_staticPrivate, _ClassExpressionStatic_instancePrivate; +export const ClassExpression = (_a = class { + constructor() { + _instances.add(this); + _context.set(this, 0); + this.value = 1; + } + }, + _context = new WeakMap(), + _instances = new WeakSet(), + _method = function _method() { return 42; }, + _a); +// Additional test with static private fields +export const ClassExpressionStatic = (_b = class { + constructor() { + _ClassExpressionStatic_instancePrivate.set(this, true); + this.exposed = "visible"; + } + }, + _ClassExpressionStatic_instancePrivate = new WeakMap(), + __setFunctionName(_b, "ClassExpressionStatic"), + _ClassExpressionStatic_staticPrivate = { value: "hidden" }, + _b); diff --git a/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.symbols b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.symbols new file mode 100644 index 00000000000..395e587de77 --- /dev/null +++ b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.symbols @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts] //// + +=== privateFieldsInClassExpressionDeclaration.ts === +export const ClassExpression = class { +>ClassExpression : Symbol(ClassExpression, Decl(privateFieldsInClassExpressionDeclaration.ts, 0, 12)) + + #context = 0; +>#context : Symbol(ClassExpression.#context, Decl(privateFieldsInClassExpressionDeclaration.ts, 0, 38)) + + #method() { return 42; } +>#method : Symbol(ClassExpression.#method, Decl(privateFieldsInClassExpressionDeclaration.ts, 1, 17)) + + public value = 1; +>value : Symbol(ClassExpression.value, Decl(privateFieldsInClassExpressionDeclaration.ts, 2, 28)) + +}; + +// Additional test with static private fields +export const ClassExpressionStatic = class { +>ClassExpressionStatic : Symbol(ClassExpressionStatic, Decl(privateFieldsInClassExpressionDeclaration.ts, 7, 12)) + + static #staticPrivate = "hidden"; +>#staticPrivate : Symbol(ClassExpressionStatic.#staticPrivate, Decl(privateFieldsInClassExpressionDeclaration.ts, 7, 44)) + + #instancePrivate = true; +>#instancePrivate : Symbol(ClassExpressionStatic.#instancePrivate, Decl(privateFieldsInClassExpressionDeclaration.ts, 8, 37)) + + public exposed = "visible"; +>exposed : Symbol(ClassExpressionStatic.exposed, Decl(privateFieldsInClassExpressionDeclaration.ts, 9, 28)) + +}; diff --git a/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.types b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.types new file mode 100644 index 00000000000..2377b1ba091 --- /dev/null +++ b/tests/baselines/reference/privateFieldsInClassExpressionDeclaration.types @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts] //// + +=== privateFieldsInClassExpressionDeclaration.ts === +export const ClassExpression = class { +>ClassExpression : typeof ClassExpression +> : ^^^^^^^^^^^^^^^^^^^^^^ +>class { #context = 0; #method() { return 42; } public value = 1;} : typeof ClassExpression +> : ^^^^^^^^^^^^^^^^^^^^^^ + + #context = 0; +>#context : number +> : ^^^^^^ +>0 : 0 +> : ^ + + #method() { return 42; } +>#method : () => number +> : ^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + public value = 1; +>value : number +> : ^^^^^^ +>1 : 1 +> : ^ + +}; + +// Additional test with static private fields +export const ClassExpressionStatic = class { +>ClassExpressionStatic : typeof ClassExpressionStatic +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>class { static #staticPrivate = "hidden"; #instancePrivate = true; public exposed = "visible";} : typeof ClassExpressionStatic +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + static #staticPrivate = "hidden"; +>#staticPrivate : string +> : ^^^^^^ +>"hidden" : "hidden" +> : ^^^^^^^^ + + #instancePrivate = true; +>#instancePrivate : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + + public exposed = "visible"; +>exposed : string +> : ^^^^^^ +>"visible" : "visible" +> : ^^^^^^^^^ + +}; diff --git a/tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts b/tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts new file mode 100644 index 00000000000..1b46bf769ac --- /dev/null +++ b/tests/cases/compiler/privateFieldsInClassExpressionDeclaration.ts @@ -0,0 +1,15 @@ +// @target: ES2015 +// @declaration: true + +export const ClassExpression = class { + #context = 0; + #method() { return 42; } + public value = 1; +}; + +// Additional test with static private fields +export const ClassExpressionStatic = class { + static #staticPrivate = "hidden"; + #instancePrivate = true; + public exposed = "visible"; +}; \ No newline at end of file