Skip to content

fix: private field in class expression emits invalid dts #61590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7485,9 +7485,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (propertySymbol.flags & SymbolFlags.Prototype) {
continue;
}
if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) {
if (context.tracker.reportPrivateInBaseOfClassExpression && (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected))) {
context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName));
}
else if (context.tracker.reportPrivateInBaseOfClassExpression && isHashPrivate(propertySymbol)) {
context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(getClonedHashPrivateName(propertySymbol)?.escapedText || "" as __String));
}
}
if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) {
context.out.truncated = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ emitClassExpressionInDeclarationFile2.ts(1,12): error TS4094: Property 'p' of ex
emitClassExpressionInDeclarationFile2.ts(1,12): error TS4094: Property 'ps' of exported anonymous class type may not be private or protected.
emitClassExpressionInDeclarationFile2.ts(16,17): error TS4094: Property 'property' of exported anonymous class type may not be private or protected.
emitClassExpressionInDeclarationFile2.ts(23,14): error TS4094: Property 'property' of exported anonymous class type may not be private or protected.
emitClassExpressionInDeclarationFile2.ts(30,12): error TS4094: Property '#p' of exported anonymous class type may not be private or protected.


==== emitClassExpressionInDeclarationFile2.ts (4 errors) ====
==== emitClassExpressionInDeclarationFile2.ts (5 errors) ====
export var noPrivates = class {
~~~~~~~~~~
!!! error TS4094: Property 'p' of exported anonymous class type may not be private or protected.
Expand Down Expand Up @@ -43,4 +44,13 @@ emitClassExpressionInDeclarationFile2.ts(23,14): error TS4094: Property 'propert

Test.getTags()
test.tags();

export var noPrivates2 = class {
~~~~~~~~~~~
!!! error TS4094: Property '#p' of exported anonymous class type may not be private or protected.
!!! related TS9027 emitClassExpressionInDeclarationFile2.ts:30:12: Add a type annotation to the variable noPrivates2.
static getTags() { }
tags() { }
#p = -1
}

84 changes: 33 additions & 51 deletions tests/baselines/reference/emitClassExpressionInDeclarationFile2.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,72 +29,54 @@ const test = new Test();

Test.getTags()
test.tags();

export var noPrivates2 = class {
static getTags() { }
tags() { }
#p = -1
}


//// [emitClassExpressionInDeclarationFile2.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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 _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Test = exports.FooItem = exports.noPrivates = void 0;
exports.WithTags = WithTags;
exports.noPrivates = (_a = /** @class */ (function () {
function class_1() {
var _a, _noPrivates2_p, _b;
export var noPrivates = (_a = class {
constructor() {
this.p = 12;
}
class_1.getTags = function () { };
class_1.prototype.tags = function () { };
return class_1;
}()),
static getTags() { }
tags() { }
},
__setFunctionName(_a, "noPrivates"),
_a.ps = -1,
_a);
// altered repro from #15066 to add private property
var FooItem = /** @class */ (function () {
function FooItem() {
export class FooItem {
constructor() {
this.property = "capitalism";
}
FooItem.prototype.foo = function () { };
return FooItem;
}());
exports.FooItem = FooItem;
function WithTags(Base) {
return /** @class */ (function (_super) {
__extends(class_2, _super);
function class_2() {
return _super !== null && _super.apply(this, arguments) || this;
}
class_2.getTags = function () { };
class_2.prototype.tags = function () { };
return class_2;
}(Base));
foo() { }
}
var Test = /** @class */ (function (_super) {
__extends(Test, _super);
function Test() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Test;
}(WithTags(FooItem)));
exports.Test = Test;
var test = new Test();
export function WithTags(Base) {
return class extends Base {
static getTags() { }
tags() { }
};
}
export class Test extends WithTags(FooItem) {
}
const test = new Test();
Test.getTags();
test.tags();
export var noPrivates2 = (_b = class {
constructor() {
_noPrivates2_p.set(this, -1);
}
static getTags() { }
tags() { }
},
_noPrivates2_p = new WeakMap(),
_b);
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,16 @@ test.tags();
>test : Symbol(test, Decl(emitClassExpressionInDeclarationFile2.ts, 24, 5))
>tags : Symbol((Anonymous class).tags, Decl(emitClassExpressionInDeclarationFile2.ts, 17, 34))

export var noPrivates2 = class {
>noPrivates2 : Symbol(noPrivates2, Decl(emitClassExpressionInDeclarationFile2.ts, 29, 10))

static getTags() { }
>getTags : Symbol(noPrivates2.getTags, Decl(emitClassExpressionInDeclarationFile2.ts, 29, 32))

tags() { }
>tags : Symbol(noPrivates2.tags, Decl(emitClassExpressionInDeclarationFile2.ts, 30, 24))

#p = -1
>#p : Symbol(noPrivates2.#p, Decl(emitClassExpressionInDeclarationFile2.ts, 31, 14))
}

Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,26 @@ test.tags();
>tags : () => void
> : ^^^^^^

export var noPrivates2 = class {
>noPrivates2 : typeof noPrivates2
> : ^^^^^^^^^^^^^^^^^^
>class { static getTags() { } tags() { } #p = -1} : typeof noPrivates2
> : ^^^^^^^^^^^^^^^^^^

static getTags() { }
>getTags : () => void
> : ^^^^^^^^^^

tags() { }
>tags : () => void
> : ^^^^^^^^^^

#p = -1
>#p : number
> : ^^^^^^
>-1 : -1
> : ^^
>1 : 1
> : ^
}

7 changes: 7 additions & 0 deletions tests/cases/compiler/emitClassExpressionInDeclarationFile2.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @declaration: true
// @target: ES6
export var noPrivates = class {
static getTags() { }
tags() { }
Expand Down Expand Up @@ -27,3 +28,9 @@ const test = new Test();

Test.getTags()
test.tags();

export var noPrivates2 = class {
static getTags() { }
tags() { }
#p = -1
}