Skip to content

Commit 3de6ed0

Browse files
authored
Merge pull request #41312 from weswigham/maybe-bind-comma-lhs
Bind comma expression LHS call expressions
2 parents ca8a15d + 4ec02a5 commit 3de6ed0

5 files changed

+90
-3
lines changed

src/compiler/binder.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,10 +1337,14 @@ namespace ts {
13371337

13381338
function bindExpressionStatement(node: ExpressionStatement): void {
13391339
bind(node.expression);
1340-
// A top level call expression with a dotted function name and at least one argument
1340+
maybeBindExpressionFlowIfCall(node.expression);
1341+
}
1342+
1343+
function maybeBindExpressionFlowIfCall(node: Expression) {
1344+
// A top level or LHS of comma expression call expression with a dotted function name and at least one argument
13411345
// is potentially an assertion and is therefore included in the control flow.
1342-
if (node.expression.kind === SyntaxKind.CallExpression) {
1343-
const call = <CallExpression>node.expression;
1346+
if (node.kind === SyntaxKind.CallExpression) {
1347+
const call = <CallExpression>node;
13441348
if (isDottedName(call.expression) && call.expression.kind !== SyntaxKind.SuperKeyword) {
13451349
currentFlow = createFlowCall(currentFlow, call);
13461350
}
@@ -1511,6 +1515,9 @@ namespace ts {
15111515
break;
15121516
}
15131517
case BindBinaryExpressionFlowState.BindToken: {
1518+
if (node.operatorToken.kind === SyntaxKind.CommaToken) {
1519+
maybeBindExpressionFlowIfCall(node.left);
1520+
}
15141521
advanceState(BindBinaryExpressionFlowState.BindRight);
15151522
maybeBind(node.operatorToken);
15161523
break;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [controlFlowCommaExpressionAssertionWithinTernary.ts]
2+
declare function assert(value: any): asserts value;
3+
4+
function foo2(param: number | null | undefined): number | null {
5+
const val = param !== undefined;
6+
return val ? (assert(param !== undefined), param) : null;
7+
// ^^^^^ Still typed as number | null | undefined
8+
}
9+
10+
//// [controlFlowCommaExpressionAssertionWithinTernary.js]
11+
"use strict";
12+
function foo2(param) {
13+
var val = param !== undefined;
14+
return val ? (assert(param !== undefined), param) : null;
15+
// ^^^^^ Still typed as number | null | undefined
16+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/compiler/controlFlowCommaExpressionAssertionWithinTernary.ts ===
2+
declare function assert(value: any): asserts value;
3+
>assert : Symbol(assert, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 0, 0))
4+
>value : Symbol(value, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 0, 24))
5+
>value : Symbol(value, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 0, 24))
6+
7+
function foo2(param: number | null | undefined): number | null {
8+
>foo2 : Symbol(foo2, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 0, 51))
9+
>param : Symbol(param, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 2, 14))
10+
11+
const val = param !== undefined;
12+
>val : Symbol(val, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 3, 9))
13+
>param : Symbol(param, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 2, 14))
14+
>undefined : Symbol(undefined)
15+
16+
return val ? (assert(param !== undefined), param) : null;
17+
>val : Symbol(val, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 3, 9))
18+
>assert : Symbol(assert, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 0, 0))
19+
>param : Symbol(param, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 2, 14))
20+
>undefined : Symbol(undefined)
21+
>param : Symbol(param, Decl(controlFlowCommaExpressionAssertionWithinTernary.ts, 2, 14))
22+
23+
// ^^^^^ Still typed as number | null | undefined
24+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
=== tests/cases/compiler/controlFlowCommaExpressionAssertionWithinTernary.ts ===
2+
declare function assert(value: any): asserts value;
3+
>assert : (value: any) => asserts value
4+
>value : any
5+
6+
function foo2(param: number | null | undefined): number | null {
7+
>foo2 : (param: number | null | undefined) => number | null
8+
>param : number | null | undefined
9+
>null : null
10+
>null : null
11+
12+
const val = param !== undefined;
13+
>val : boolean
14+
>param !== undefined : boolean
15+
>param : number | null | undefined
16+
>undefined : undefined
17+
18+
return val ? (assert(param !== undefined), param) : null;
19+
>val ? (assert(param !== undefined), param) : null : number | null
20+
>val : boolean
21+
>(assert(param !== undefined), param) : number | null
22+
>assert(param !== undefined), param : number | null
23+
>assert(param !== undefined) : void
24+
>assert : (value: any) => asserts value
25+
>param !== undefined : boolean
26+
>param : number | null | undefined
27+
>undefined : undefined
28+
>param : number | null
29+
>null : null
30+
31+
// ^^^^^ Still typed as number | null | undefined
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @strict: true
2+
declare function assert(value: any): asserts value;
3+
4+
function foo2(param: number | null | undefined): number | null {
5+
const val = param !== undefined;
6+
return val ? (assert(param !== undefined), param) : null;
7+
// ^^^^^ Still typed as number | null | undefined
8+
}

0 commit comments

Comments
 (0)