Skip to content

Commit 3784ace

Browse files
committed
Fix(checker): Allow element access expressions in computed property names if argument is literal (Fixes #25083)
1 parent c574e40 commit 3784ace

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ import {
742742
isShorthandAmbientModuleSymbol,
743743
isShorthandPropertyAssignment,
744744
isSideEffectImport,
745+
isSignedNumericLiteral,
745746
isSingleOrDoubleQuote,
746747
isSourceFile,
747748
isSourceFileJS,
@@ -13720,14 +13721,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1372013721
&& isTypeUsableAsIndexSignature(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached((node as ElementAccessExpression).argumentExpression));
1372113722
}
1372213723

13723-
function isLateBindableAST(node: DeclarationName) {
13724-
if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
13725-
return false;
13724+
function isLateBindableExpression(expr: Expression): boolean {
13725+
while (isElementAccessExpression(expr)) {
13726+
const argument = skipParentheses(expr.argumentExpression);
13727+
if (!isStringOrNumericLiteralLike(argument) && !isSignedNumericLiteral(argument)) return false;
13728+
expr = expr.expression;
1372613729
}
13727-
const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
1372813730
return isEntityNameExpression(expr);
1372913731
}
1373013732

13733+
function isLateBindableAST(node: DeclarationName) {
13734+
if (isComputedPropertyName(node)) {
13735+
return isLateBindableExpression(node.expression);
13736+
}
13737+
else if (isElementAccessExpression(node)) {
13738+
return isLateBindableExpression(node.argumentExpression);
13739+
}
13740+
return false;
13741+
}
13742+
1373113743
function isTypeUsableAsIndexSignature(type: Type): boolean {
1373213744
return isTypeAssignableTo(type, stringNumberSymbolType);
1373313745
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
enum Type {
3+
Foo = 'foo',
4+
'3x14' = '3x14'
5+
}
6+
7+
type TypeMap = {
8+
[Type.Foo]: 1;
9+
[Type['3x14']]: 2;
10+
}
11+
12+
const t: TypeMap = {
13+
'foo': 1,
14+
'3x14': 2
15+
};
16+
17+
enum Numeric {
18+
Negative = -1,
19+
Zero = 0
20+
}
21+
22+
type NumericMap = {
23+
// Valid: Accessing enum member via string literal for the name
24+
[Numeric['Negative']]: number;
25+
[Numeric['Zero']]: number;
26+
// Valid: Parenthesized access
27+
[Numeric[('Negative')]]: number;
28+
}
29+

0 commit comments

Comments
 (0)