Skip to content
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
14 changes: 11 additions & 3 deletions tsc/internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24634,10 +24634,18 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R
name := expr.AsElementAccessExpression().ArgumentExpression.Text()
member := rootSymbol.Exports()[name]
if member != nil {
if location != nil {
return c.evaluateEnumMember(expr, member, location)
// Follow aliases like resolveEntityName (property-access path), e.g. export import C = F.A.
for member.Flags()&ast.SymbolFlagsValue == 0 && member.Flags()&ast.SymbolFlagsAlias != 0 {
member = c.resolveAlias(member)
}
// Merged namespace+enum symbols can export non-enum members (e.g. a class).
// Only treat EnumMember exports as constant enum values — mirror the identifier path.
if member.Flags()&ast.SymbolFlagsEnumMember != 0 {
if location != nil {
return c.evaluateEnumMember(expr, member, location)
}
return c.getEnumMemberValue(member.ValueDeclaration())
}
return c.getEnumMemberValue(member.ValueDeclaration())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
enumInitializerNamespaceExportElementAccess.ts(8,9): error TS18033: Type 'typeof C' is not assignable to type 'number' as required for computed enum member values.


==== enumInitializerNamespaceExportElementAccess.ts (1 errors) ====
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock

namespace E {
export class C {}
}
enum E {
D = E["C"],
~~~~~~
!!! error TS18033: Type 'typeof C' is not assignable to type 'number' as required for computed enum member values.
}

// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
enum F {
A = 1,
}
namespace E2 {
export import C = F.A;
}
enum E2 {
D = E2["C"],
Next,
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//// [tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts] ////

//// [enumInitializerNamespaceExportElementAccess.ts]
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock

namespace E {
export class C {}
}
enum E {
D = E["C"],
}

// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
enum F {
A = 1,
}
namespace E2 {
export import C = F.A;
}
enum E2 {
D = E2["C"],
Next,
}


//// [enumInitializerNamespaceExportElementAccess.js]
"use strict";
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock
var E;
(function (E) {
class C {
}
E.C = C;
})(E || (E = {}));
(function (E) {
E[E["D"] = E["C"]] = "D";
})(E || (E = {}));
// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
var F;
(function (F) {
F[F["A"] = 1] = "A";
})(F || (F = {}));
var E2;
(function (E2) {
E2.C = F.A;
})(E2 || (E2 = {}));
(function (E2) {
E2[E2["D"] = 1] = "D";
E2[E2["Next"] = 2] = "Next";
})(E2 || (E2 = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//// [tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts] ////

=== enumInitializerNamespaceExportElementAccess.ts ===
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock

namespace E {
>E : Symbol(E, Decl(enumInitializerNamespaceExportElementAccess.ts, 0, 0), Decl(enumInitializerNamespaceExportElementAccess.ts, 5, 1))

export class C {}
>C : Symbol(C, Decl(enumInitializerNamespaceExportElementAccess.ts, 3, 13))
}
enum E {
>E : Symbol(E, Decl(enumInitializerNamespaceExportElementAccess.ts, 0, 0), Decl(enumInitializerNamespaceExportElementAccess.ts, 5, 1))

D = E["C"],
>D : Symbol(E.D, Decl(enumInitializerNamespaceExportElementAccess.ts, 6, 8))
>E : Symbol(E, Decl(enumInitializerNamespaceExportElementAccess.ts, 0, 0), Decl(enumInitializerNamespaceExportElementAccess.ts, 5, 1))
>"C" : Symbol(E.C, Decl(enumInitializerNamespaceExportElementAccess.ts, 3, 13))
}

// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
enum F {
>F : Symbol(F, Decl(enumInitializerNamespaceExportElementAccess.ts, 8, 1))

A = 1,
>A : Symbol(F.A, Decl(enumInitializerNamespaceExportElementAccess.ts, 11, 8))
}
namespace E2 {
>E2 : Symbol(E2, Decl(enumInitializerNamespaceExportElementAccess.ts, 13, 1), Decl(enumInitializerNamespaceExportElementAccess.ts, 16, 1))

export import C = F.A;
>C : Symbol(C, Decl(enumInitializerNamespaceExportElementAccess.ts, 14, 14))
>F : Symbol(F, Decl(enumInitializerNamespaceExportElementAccess.ts, 8, 1))
>A : Symbol(C, Decl(enumInitializerNamespaceExportElementAccess.ts, 11, 8))
}
enum E2 {
>E2 : Symbol(E2, Decl(enumInitializerNamespaceExportElementAccess.ts, 13, 1), Decl(enumInitializerNamespaceExportElementAccess.ts, 16, 1))

D = E2["C"],
>D : Symbol(E2.D, Decl(enumInitializerNamespaceExportElementAccess.ts, 17, 9))
>E2 : Symbol(E2, Decl(enumInitializerNamespaceExportElementAccess.ts, 13, 1), Decl(enumInitializerNamespaceExportElementAccess.ts, 16, 1))
>"C" : Symbol(E2.C, Decl(enumInitializerNamespaceExportElementAccess.ts, 14, 14))

Next,
>Next : Symbol(E2.Next, Decl(enumInitializerNamespaceExportElementAccess.ts, 18, 16))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//// [tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts] ////

=== enumInitializerNamespaceExportElementAccess.ts ===
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock

namespace E {
>E : typeof E

export class C {}
>C : C
}
enum E {
>E : E

D = E["C"],
>D : E.D
>E["C"] : typeof E.C
>E : typeof E
>"C" : "C"
}

// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
enum F {
>F : F

A = 1,
>A : F.A
>1 : 1
}
namespace E2 {
>E2 : typeof E2

export import C = F.A;
>C : F.A
>F : F
>A : F.A
}
enum E2 {
>E2 : E2

D = E2["C"],
>D : E2.D
>E2["C"] : F
>E2 : typeof E2
>"C" : "C"

Next,
>Next : E2.Next
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Namespace export merged with enum must not be treated as an enum member via E["C"].
// Previously panicked: Unhandled case in Node.MemberList: KindModuleBlock

namespace E {
export class C {}
}
enum E {
D = E["C"],
}

// Alias exports that resolve to enum members must still constant-evaluate (like E.C).
enum F {
A = 1,
}
namespace E2 {
export import C = F.A;
}
enum E2 {
D = E2["C"],
Next,
}