Skip to content

Commit 3298a5e

Browse files
author
hayatexe
committed
fix(25083): allow element access expressions with string or numeric literal arguments as computed properties
1 parent 3472548 commit 3298a5e

File tree

7 files changed

+78
-7
lines changed

7 files changed

+78
-7
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13785,12 +13785,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1378513785
&& isTypeUsableAsIndexSignature(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached((node as ElementAccessExpression).argumentExpression));
1378613786
}
1378713787

13788+
function isEntityNameExpressionOrElementAccess(node: Node): boolean {
13789+
if (isEntityNameExpression(node)) {
13790+
return true;
13791+
}
13792+
if (isElementAccessExpression(node) && isStringOrNumericLiteralLike(skipParentheses(node.argumentExpression))) {
13793+
return isEntityNameExpressionOrElementAccess(node.expression);
13794+
}
13795+
return false;
13796+
}
13797+
1378813798
function isLateBindableAST(node: DeclarationName) {
1378913799
if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
1379013800
return false;
1379113801
}
1379213802
const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
13793-
return isEntityNameExpression(expr);
13803+
return isEntityNameExpressionOrElementAccess(expr);
1379413804
}
1379513805

1379613806
function isTypeUsableAsIndexSignature(type: Type): boolean {
@@ -52956,7 +52966,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5295652966

5295752967
function checkGrammarForInvalidDynamicName(node: DeclarationName, message: DiagnosticMessage) {
5295852968
// 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
52959-
if (isNonBindableDynamicName(node) && !isEntityNameExpression(isElementAccessExpression(node) ? skipParentheses(node.argumentExpression) : (node as ComputedPropertyName).expression)) {
52969+
if (isNonBindableDynamicName(node) && !isEntityNameExpressionOrElementAccess(isElementAccessExpression(node) ? skipParentheses(node.argumentExpression) : (node as ComputedPropertyName).expression)) {
5296052970
return grammarErrorOnNode(node, message);
5296152971
}
5296252972
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//// [tests/cases/compiler/computedPropertyWithEnumKey.ts] ////
2+
3+
//// [computedPropertyWithEnumKey.ts]
4+
enum Type { Foo = 'foo', '3x14' = '3.14' } type TypeMap = { [Type.Foo]: any; [Type['3x14']]: any; };
5+
6+
7+
//// [computedPropertyWithEnumKey.js]
8+
"use strict";
9+
var Type;
10+
(function (Type) {
11+
Type["Foo"] = "foo";
12+
Type["3x14"] = "3.14";
13+
})(Type || (Type = {}));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [tests/cases/compiler/computedPropertyWithEnumKey.ts] ////
2+
3+
=== computedPropertyWithEnumKey.ts ===
4+
enum Type { Foo = 'foo', '3x14' = '3.14' } type TypeMap = { [Type.Foo]: any; [Type['3x14']]: any; };
5+
>Type : Symbol(Type, Decl(computedPropertyWithEnumKey.ts, 0, 0))
6+
>Foo : Symbol(Type.Foo, Decl(computedPropertyWithEnumKey.ts, 0, 11))
7+
>'3x14' : Symbol(Type['3x14'], Decl(computedPropertyWithEnumKey.ts, 0, 24))
8+
>TypeMap : Symbol(TypeMap, Decl(computedPropertyWithEnumKey.ts, 0, 42))
9+
>[Type.Foo] : Symbol([Type.Foo], Decl(computedPropertyWithEnumKey.ts, 0, 59))
10+
>Type.Foo : Symbol(Type.Foo, Decl(computedPropertyWithEnumKey.ts, 0, 11))
11+
>Type : Symbol(Type, Decl(computedPropertyWithEnumKey.ts, 0, 0))
12+
>Foo : Symbol(Type.Foo, Decl(computedPropertyWithEnumKey.ts, 0, 11))
13+
>[Type['3x14']] : Symbol([Type['3x14']], Decl(computedPropertyWithEnumKey.ts, 0, 76))
14+
>Type : Symbol(Type, Decl(computedPropertyWithEnumKey.ts, 0, 0))
15+
>'3x14' : Symbol(Type['3x14'], Decl(computedPropertyWithEnumKey.ts, 0, 24))
16+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [tests/cases/compiler/computedPropertyWithEnumKey.ts] ////
2+
3+
=== computedPropertyWithEnumKey.ts ===
4+
enum Type { Foo = 'foo', '3x14' = '3.14' } type TypeMap = { [Type.Foo]: any; [Type['3x14']]: any; };
5+
>Type : Type
6+
> : ^^^^
7+
>Foo : Type.Foo
8+
> : ^^^^^^^^
9+
>'foo' : "foo"
10+
> : ^^^^^
11+
>'3x14' : (typeof Type)["3x14"]
12+
> : ^^^^^^^^^^^^^^^^^^^^^
13+
>'3.14' : "3.14"
14+
> : ^^^^^^
15+
>TypeMap : TypeMap
16+
> : ^^^^^^^
17+
>[Type.Foo] : any
18+
>Type.Foo : Type.Foo
19+
> : ^^^^^^^^
20+
>Type : typeof Type
21+
> : ^^^^^^^^^^^
22+
>Foo : Type.Foo
23+
> : ^^^^^^^^
24+
>[Type['3x14']] : any
25+
>Type['3x14'] : (typeof Type)["3x14"]
26+
> : ^^^^^^^^^^^^^^^^^^^^^
27+
>Type : typeof Type
28+
> : ^^^^^^^^^^^
29+
>'3x14' : "3x14"
30+
> : ^^^^^^
31+

tests/baselines/reference/isolatedDeclarationLazySymbols.errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
isolatedDeclarationLazySymbols.ts(1,17): error TS9007: Function must have an explicit return type annotation with --isolatedDeclarations.
2+
isolatedDeclarationLazySymbols.ts(12,1): error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
23
isolatedDeclarationLazySymbols.ts(13,1): error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
3-
isolatedDeclarationLazySymbols.ts(16,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.
44
isolatedDeclarationLazySymbols.ts(16,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
55
isolatedDeclarationLazySymbols.ts(21,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
66
isolatedDeclarationLazySymbols.ts(22,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
@@ -22,15 +22,15 @@ isolatedDeclarationLazySymbols.ts(22,5): error TS9038: Computed property names o
2222
} as const
2323

2424
foo[o["prop.inner"]] ="A";
25+
~~~~~~~~~~~~~~~~~~~~
26+
!!! error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
2527
foo[o.prop.inner] = "B";
2628
~~~~~~~~~~~~~~~~~
2729
!!! error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
2830

2931
export class Foo {
3032
[o["prop.inner"]] ="A"
3133
~~~~~~~~~~~~~~~~~
32-
!!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.
33-
~~~~~~~~~~~~~~~~~
3434
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
3535
[o.prop.inner] = "B"
3636
}

tests/baselines/reference/isolatedDeclarationLazySymbols.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ const o = {
4040
foo[o["prop.inner"]] ="A";
4141
>foo[o["prop.inner"]] ="A" : "A"
4242
> : ^^^
43-
>foo[o["prop.inner"]] : any
44-
> : ^^^
43+
>foo[o["prop.inner"]] : string
44+
> : ^^^^^^
4545
>foo : typeof foo
4646
> : ^^^^^^^^^^
4747
>o["prop.inner"] : "a"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enum Type { Foo = 'foo', '3x14' = '3.14' } type TypeMap = { [Type.Foo]: any; [Type['3x14']]: any; };

0 commit comments

Comments
 (0)