diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index d392785d4181f..c75355f13e696 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -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()) } } } diff --git a/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.errors.txt b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.errors.txt new file mode 100644 index 0000000000000..7818ffce72b99 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.errors.txt @@ -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, + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.js b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.js new file mode 100644 index 0000000000000..e5312dbec4852 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.js @@ -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 = {})); diff --git a/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.symbols b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.symbols new file mode 100644 index 0000000000000..f5e6db5dfc5fe --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.symbols @@ -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)) +} + diff --git a/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.types b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.types new file mode 100644 index 0000000000000..ade9d221407d6 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumInitializerNamespaceExportElementAccess.types @@ -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 +} + diff --git a/tsc/testdata/tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts b/tsc/testdata/tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts new file mode 100644 index 0000000000000..9a40c89e1baf4 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/enumInitializerNamespaceExportElementAccess.ts @@ -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, +}