diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 599338b150..396187ba09 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1047,24 +1047,9 @@ namespace ts { } } - function isLogicalAssignmentExpressioin(node: Node) { - while (true) { - if (isParenthesizedExpression(node)) { - node = node.expression; - } - else { - return isBinaryExpression(node) && isLogicalAssignmentOperator(node.operatorToken.kind); - } - } - } - - function isTopLevelLogicalAssignmentExpression(node: Node): boolean { - while (isParenthesizedExpression(node.parent)) { - node = node.parent; - } - return !isStatementCondition(node) && - !isLogicalAssignmentExpressioin(node.parent) && - !(isOptionalChain(node.parent) && node.parent.expression === node); + function isLogicalAssignmentExpression(node: Node) { + node = skipParentheses(node); + return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind); } function isTopLevelLogicalExpression(node: Node): boolean { @@ -1073,6 +1058,7 @@ namespace ts { node = node.parent; } return !isStatementCondition(node) && + !isLogicalAssignmentExpression(node.parent) && !isLogicalExpression(node.parent) && !(isOptionalChain(node.parent) && node.parent.expression === node); } @@ -1089,7 +1075,7 @@ namespace ts { function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!node || !isLogicalAssignmentExpressioin(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { + if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } @@ -1189,24 +1175,6 @@ namespace ts { currentFlow = finishFlowLabel(postIfLabel); } - function bindLogicalAssignmentExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { - const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { - bindCondition(node.left, preRightLabel, falseTarget); - } - else { - bindCondition(node.left, trueTarget, preRightLabel); - } - currentFlow = finishFlowLabel(preRightLabel); - bind(node.operatorToken); - - doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); - bindAssignmentTargetFlow(node.left); - - addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); - } - function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { bind(node.expression); if (node.kind === SyntaxKind.ReturnStatement) { @@ -1448,9 +1416,9 @@ namespace ts { } } - function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { + function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -1458,7 +1426,17 @@ namespace ts { } currentFlow = finishFlowLabel(preRightLabel); bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget); + + if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) { + doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); + bindAssignmentTargetFlow(node.left); + + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); + } + else { + bindCondition(node.right, trueTarget, falseTarget); + } } function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { @@ -1544,25 +1522,15 @@ namespace ts { // TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions // we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too // For now, though, since the common cases are chained `+`, leaving it recursive is fine - if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken || + isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); - bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); + bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); currentFlow = finishFlowLabel(postExpressionLabel); } else { - bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); - } - completeNode(); - } - else if(isLogicalAssignmentOperator(operator)) { - if (isTopLevelLogicalAssignmentExpression(node)) { - const postExpressionLabel = createBranchLabel(); - bindLogicalAssignmentExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); - } - else { - bindLogicalAssignmentExpression(node, currentTrueTarget!, currentFalseTarget!); + bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!); } completeNode(); } @@ -3656,7 +3624,7 @@ namespace ts { if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { transformFlags |= TransformFlags.AssertES2020; } - else if (isLogicalAssignmentOperator(operatorTokenKind)) { + else if (isLogicalOrCoalescingAssignmentOperator(operatorTokenKind)) { transformFlags |= TransformFlags.AssertESNext; } else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89ee4693ff..f53eb42e6a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28596,7 +28596,7 @@ namespace ts { getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.BarBarEqualsToken) { - checkAssignmentOperator(resultType); + checkAssignmentOperator(rightType); } return resultType; } @@ -28606,7 +28606,7 @@ namespace ts { getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.QuestionQuestionEqualsToken) { - checkAssignmentOperator(resultType); + checkAssignmentOperator(rightType); } return resultType; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index b9bbbffe5f..6edbb65bf4 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -18,7 +18,7 @@ namespace ts { switch (node.kind) { case SyntaxKind.BinaryExpression: const binaryExpression = node; - if (isLogicalAssignmentOperator(binaryExpression.operatorToken.kind)) { + if (isLogicalOrCoalescingAssignmentOperator(binaryExpression.operatorToken.kind)) { return transformLogicalAssignmentOperators(binaryExpression); } // falls through @@ -29,7 +29,7 @@ namespace ts { function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult { const operator = binaryExpression.operatorToken; - if (isCompoundAssignment(operator.kind) && isLogicalAssignmentOperator(operator.kind)) { + if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) { const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); const left = visitNode(binaryExpression.left, visitor, isExpression); const right = visitNode(binaryExpression.right, visitor, isExpression); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 58a6933429..e0bcfebb1b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2594,7 +2594,7 @@ namespace ts { switch (parent.kind) { case SyntaxKind.BinaryExpression: const binaryOperator = (parent).operatorToken.kind; - return isAssignmentOperator(binaryOperator) && !isLogicalAssignmentOperator(binaryOperator) && (parent).left === node ? + return isAssignmentOperator(binaryOperator) && !isLogicalOrCoalescingAssignmentOperator(binaryOperator) && (parent).left === node ? binaryOperator === SyntaxKind.EqualsToken ? AssignmentKind.Definite : AssignmentKind.Compound : AssignmentKind.None; case SyntaxKind.PrefixUnaryExpression: @@ -3378,10 +3378,6 @@ namespace ts { return 14; case SyntaxKind.AsteriskAsteriskToken: return 15; - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: - return 16; } // -1 is lower than all other precedences. Returning it will cause binary expression @@ -4454,7 +4450,7 @@ namespace ts { || token === SyntaxKind.ExclamationToken; } - export function isLogicalAssignmentOperator(token: SyntaxKind): boolean { + export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): boolean { return token === SyntaxKind.BarBarEqualsToken || token === SyntaxKind.AmpersandAmpersandEqualsToken || token === SyntaxKind.QuestionQuestionEqualsToken; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index ec17923d86..bf6b918086 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -785,12 +785,6 @@ namespace ts.codefix { } break; - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - // TODO: infer here - break; - case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: case SyntaxKind.InstanceOfKeyword: diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt index 4eec0ce2d1..c7f29aa3a3 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).js b/tests/baselines/reference/logicalAssignment7(target=es2015).js index 4ac2a4159b..a0f67c80e5 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).js @@ -14,12 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment7.js] "use strict"; function foo1(results, results1) { - (results || (results = results1) || (results || (results = results1) = [])).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - var _a; - ((_a = results !== null && results !== void 0 ? results : (results = results1)) !== null && _a !== void 0 ? _a : (results !== null && results !== void 0 ? results : (results = results1) = [])).push(100); + (results !== null && results !== void 0 ? results : (results = results1 !== null && results1 !== void 0 ? results1 : (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = results1) && (results && (results = results1) = [])).push(100); + (results && (results = results1 && (results1 = []))).push(100); } diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).types b/tests/baselines/reference/logicalAssignment7(target=es2015).types index b46c67c14b..250fb4072f 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt index 4eec0ce2d1..c7f29aa3a3 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).js b/tests/baselines/reference/logicalAssignment7(target=es2020).js index 8c0438acca..38a14a6419 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).js @@ -14,11 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment7.js] "use strict"; function foo1(results, results1) { - (results || (results = results1) || (results || (results = results1) = [])).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - (results ?? (results = results1) ?? (results ?? (results = results1) = [])).push(100); + (results ?? (results = results1 ?? (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = results1) && (results && (results = results1) = [])).push(100); + (results && (results = results1 && (results1 = []))).push(100); } diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).types b/tests/baselines/reference/logicalAssignment7(target=es2020).types index b46c67c14b..250fb4072f 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt index 4eec0ce2d1..c7f29aa3a3 100644 --- a/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).types b/tests/baselines/reference/logicalAssignment7(target=esnext).types index b46c67c14b..250fb4072f 100644 --- a/tests/baselines/reference/logicalAssignment7(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number