Skip to content

Commit 0a194f9

Browse files
author
Kanchalai Tanglertsampan
committed
Emit parenthesis around propert/element access expression of casted object literal expression
1 parent dd48dd1 commit 0a194f9

9 files changed

+101
-4
lines changed

src/compiler/transformers/ts.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,14 +2324,19 @@ namespace ts {
23242324
// code if the casted expression has a lower precedence than the rest of the
23252325
// expression.
23262326
//
2327+
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
2328+
// preserve the position information of the original expression.
2329+
const partialExpression = createPartiallyEmittedExpression(expression, node);
2330+
23272331
// Due to the auto-parenthesization rules used by the visitor and factory functions
23282332
// we can safely elide the parentheses here, as a new synthetic
23292333
// ParenthesizedExpression will be inserted if we remove parentheses too
23302334
// aggressively.
2331-
//
2332-
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
2333-
// preserve the position information of the original expression.
2334-
return createPartiallyEmittedExpression(expression, node);
2335+
// However, auto-parenthesization will not preserve parenthesis for the following case: ({ "1": "one", "2": "two" } as { [key: string]: string })[x].
2336+
// so we have to manually preserve it here.
2337+
const shouldPreserveParen = (isPropertyAccessExpression(node.parent) || isElementAccessExpression(node.parent)) &&
2338+
isObjectLiteralExpression((expression as PartiallyEmittedExpression).expression);
2339+
return shouldPreserveParen ? createParen(partialExpression) : partialExpression;
23352340
}
23362341

23372342
return visitEachChild(node, visitor, context);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts]
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
4+
5+
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES5.js]
6+
(function (x) { return ({ "1": "one", "2": "two" })[x]; });
7+
(function (x) { return ({ "1": "one", "2": "two" }).x; });
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts ===
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 1))
4+
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 41))
5+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 1))
6+
7+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
8+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 1, 1))
9+
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 1, 41))
10+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts ===
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x] : (x: any) => string
4+
>x : any
5+
>({ "1": "one", "2": "two" } as { [key: string]: string })[x] : string
6+
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
7+
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
8+
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
9+
>"one" : "one"
10+
>"two" : "two"
11+
>key : string
12+
>x : any
13+
14+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
15+
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x : (x: any) => string
16+
>x : any
17+
>({ "1": "one", "2": "two" } as { [key: string]: string }).x : string
18+
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
19+
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
20+
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
21+
>"one" : "one"
22+
>"two" : "two"
23+
>key : string
24+
>x : string
25+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts]
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
4+
5+
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES6.js]
6+
(x) => ({ "1": "one", "2": "two" })[x];
7+
(x) => ({ "1": "one", "2": "two" }).x;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts ===
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 1))
4+
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 41))
5+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 1))
6+
7+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
8+
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 1, 1))
9+
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 1, 41))
10+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts ===
2+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
3+
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x] : (x: any) => string
4+
>x : any
5+
>({ "1": "one", "2": "two" } as { [key: string]: string })[x] : string
6+
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
7+
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
8+
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
9+
>"one" : "one"
10+
>"two" : "two"
11+
>key : string
12+
>x : any
13+
14+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
15+
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x : (x: any) => string
16+
>x : any
17+
>({ "1": "one", "2": "two" } as { [key: string]: string }).x : string
18+
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
19+
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
20+
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
21+
>"one" : "one"
22+
>"two" : "two"
23+
>key : string
24+
>x : string
25+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// @target: es5
2+
3+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
4+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// @target: es6
2+
3+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
4+
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;

0 commit comments

Comments
 (0)