← Back to PR Bug Fix Database
7
High
PR-TypeScript-25083

Fix: Enum keys not accepted as computed properties with non-identifier names

HighRepo: microsoft/TypeScriptDate: June 8, 2026
PR FixTypeScriptBug FixEdge CaseEnumsType System

// The Bug

How microsoft/TypeScript#25083 fixed enum keys in computed properties — why computed property names with non-identifier enum values were rejected by the type checker.

Repository
microsoft/TypeScript
Issue
Status
closed-not-merged

// Root Cause

In `src/compiler/checker.ts`, the `isLateBindableAST` function determines whether a declaration name can be "late bound" (resolved during type checking rather than during binding). The original code [2]:

```ts
function isLateBindableAST(node: DeclarationName) {
if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
return false;
}
const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
return isEntityNameExpression(expr);
}
```

`isEntityNameExpression` only returns `true` for identifiers (`foo`) and dotted names (`A.B`). String literal expressions like `Keys['my-key']` are `ElementAccessExpression` (not entity name expressions), so they were rejected by the guard. But `Keys['my-key']` is a perfectly valid computed property name — the string literal `'my-key'` should be accepted as the property key [2].

---

// The Fix

Diff showing the exact changes made to fix the bug.

@@ -13785,13 +13785,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
             && isTypeUsableAsIndexSignature(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached((node as ElementAccessExpression).argumentExpression));
     }

-    function isLateBindableAST(node: DeclarationName) {
-        if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
-            return false;
-        }
-        const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
-        return isEntityNameExpression(expr);
-    }
+    function isLateBindableAST(node: DeclarationName) {
+        if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
+            return false;
+        }
+        const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
+        return isEntityNameExpression(expr) ||
+            isElementAccessExpression(expr) && isStringLiteral(expr.argumentExpression) && isEntityNameExpression(expr.expression);
+    }