From 10c4c32bf5a150ce3cb67c0f0a13e4a9b7333989 Mon Sep 17 00:00:00 2001 From: Rayan Salhab Date: Thu, 26 Mar 2026 21:24:48 +0000 Subject: [PATCH] fix: allow enum member references with non-identifier names as computed property names in type literals Fixes #25083 Previously, using an enum member with a non-identifier name (like '3x14') as a computed property name in a type literal would incorrectly produce an error: 'A computed property name in a type literal must refer to an expression whose type is a literal type or a unique symbol type.' The fix updates checkGrammarForInvalidDynamicName to also allow element access expressions where: 1. The argument expression is a string or number literal 2. The expression being accessed is an entity name expression (like Type in Type['3x14']) This enables patterns like: enum Type { '3x14' = '3x14' } type TypeMap = { [Type['3x14']]: any } // Now works! --- src/compiler/checker.ts | 13 +++++++++++-- ...mputedPropertyNameWithInvalidIdentifier.ts | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/cases/compiler/enumComputedPropertyNameWithInvalidIdentifier.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..296cdf2c3b4f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -52971,8 +52971,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarForInvalidDynamicName(node: DeclarationName, message: DiagnosticMessage) { // Even non-bindable names are allowed as late-bound implied index signatures so long as the name is a simple `a.b.c` type name expression - if (isNonBindableDynamicName(node) && !isEntityNameExpression(isElementAccessExpression(node) ? skipParentheses(node.argumentExpression) : (node as ComputedPropertyName).expression)) { - return grammarErrorOnNode(node, message); + if (isNonBindableDynamicName(node)) { + // Allow element access expressions with string/number literal arguments on entity name expressions + // This enables enum member references like `Type['3x14']` to be used as computed property names + if (isElementAccessExpression(node)) { + if (isStringOrNumberLiteralExpression(node.argumentExpression) && isEntityNameExpression(node.expression)) { + return; + } + } + if (!isEntityNameExpression(isElementAccessExpression(node) ? skipParentheses(node.argumentExpression) : (node as ComputedPropertyName).expression)) { + return grammarErrorOnNode(node, message); + } } } diff --git a/tests/cases/compiler/enumComputedPropertyNameWithInvalidIdentifier.ts b/tests/cases/compiler/enumComputedPropertyNameWithInvalidIdentifier.ts new file mode 100644 index 0000000000000..156e4c832f37f --- /dev/null +++ b/tests/cases/compiler/enumComputedPropertyNameWithInvalidIdentifier.ts @@ -0,0 +1,19 @@ +// @strict: true +// @noEmit: true + +// Repro from #25083 + +enum Type { + Foo = 'foo', + '3x14' = '3x14' +} + +type TypeMap = { + [Type.Foo]: any + [Type['3x14']]: any +} + +const x: TypeMap = { + [Type.Foo]: 1, + [Type['3x14']]: 2 +};