Skip to content

Commit 0ea45f3

Browse files
committed
fix(39373): add diagnostic message about using a private name for class declarations without name
1 parent 030f5e8 commit 0ea45f3

File tree

7 files changed

+99
-2
lines changed

7 files changed

+99
-2
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,10 @@
30413041
"category": "Error",
30423042
"code": 4020
30433043
},
3044+
"'extends' clause of exported class has or is using private name '{0}'.": {
3045+
"category": "Error",
3046+
"code": 4021
3047+
},
30443048
"'extends' clause of exported interface '{0}' has or is using private name '{1}'.": {
30453049
"category": "Error",
30463050
"code": 4022

src/compiler/transformers/declarations/diagnostics.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,12 @@ namespace ts {
447447
function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic {
448448
let diagnosticMessage: DiagnosticMessage;
449449
// Heritage clause is written by user so it can always be named
450-
if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
450+
if (isClassDeclaration(node.parent.parent)) {
451451
// Class or Interface implemented/extended is inaccessible
452452
diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ?
453453
Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
454-
Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
454+
node.parent.parent.name ? Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1 :
455+
Diagnostics.extends_clause_of_exported_class_has_or_is_using_private_name_0;
455456
}
456457
else {
457458
// interface is inaccessible
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tests/cases/compiler/b.ts(2,30): error TS4021: 'extends' clause of exported class has or is using private name 'A'.
2+
3+
4+
==== tests/cases/compiler/b.ts (1 errors) ====
5+
const { A } = require("./a");
6+
export default class extends A {}
7+
~
8+
!!! error TS4021: 'extends' clause of exported class has or is using private name 'A'.
9+
10+
==== /node_modules/@types/node/index.d.ts (0 errors) ====
11+
declare const require: any;
12+
13+
==== tests/cases/compiler/a.ts (0 errors) ====
14+
export class A {}
15+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//// [tests/cases/compiler/declarationEmitExpressionInExtends6.ts] ////
2+
3+
//// [index.d.ts]
4+
declare const require: any;
5+
6+
//// [a.ts]
7+
export class A {}
8+
9+
//// [b.ts]
10+
const { A } = require("./a");
11+
export default class extends A {}
12+
13+
14+
//// [b.js]
15+
"use strict";
16+
var __extends = (this && this.__extends) || (function () {
17+
var extendStatics = function (d, b) {
18+
extendStatics = Object.setPrototypeOf ||
19+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
20+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
21+
return extendStatics(d, b);
22+
};
23+
return function (d, b) {
24+
extendStatics(d, b);
25+
function __() { this.constructor = d; }
26+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
27+
};
28+
})();
29+
exports.__esModule = true;
30+
var A = require("./a").A;
31+
var default_1 = /** @class */ (function (_super) {
32+
__extends(default_1, _super);
33+
function default_1() {
34+
return _super !== null && _super.apply(this, arguments) || this;
35+
}
36+
return default_1;
37+
}(A));
38+
exports["default"] = default_1;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/compiler/b.ts ===
2+
const { A } = require("./a");
3+
>A : Symbol(A, Decl(b.ts, 0, 7))
4+
>require : Symbol(require, Decl(index.d.ts, 0, 13))
5+
6+
export default class extends A {}
7+
>A : Symbol(A, Decl(b.ts, 0, 7))
8+
9+
=== /node_modules/@types/node/index.d.ts ===
10+
declare const require: any;
11+
>require : Symbol(require, Decl(index.d.ts, 0, 13))
12+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/b.ts ===
2+
const { A } = require("./a");
3+
>A : any
4+
>require("./a") : any
5+
>require : any
6+
>"./a" : "./a"
7+
8+
export default class extends A {}
9+
>A : any
10+
11+
=== /node_modules/@types/node/index.d.ts ===
12+
declare const require: any;
13+
>require : any
14+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @module: commonjs
2+
// @declaration: true
3+
// @types: node
4+
5+
// @Filename: /node_modules/@types/node/index.d.ts
6+
declare const require: any;
7+
8+
// @Filename: a.ts
9+
export class A {}
10+
11+
// @Filename: b.ts
12+
const { A } = require("./a");
13+
export default class extends A {}

0 commit comments

Comments
 (0)