mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
Account for right operands & fix a weird error message for leftmost nullish literals in checkNullishCoalesceOperands (#59569)
This commit is contained in:
parent
edc497bb2b
commit
2bed7feee8
@ -39847,24 +39847,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind));
|
||||
}
|
||||
|
||||
const leftTarget = skipOuterExpressions(left, OuterExpressionKinds.All);
|
||||
const nullishSemantics = getSyntacticNullishnessSemantics(leftTarget);
|
||||
if (nullishSemantics !== PredicateSemantics.Sometimes) {
|
||||
if (node.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
error(leftTarget, Diagnostics.This_binary_expression_is_never_nullish_Are_you_missing_parentheses);
|
||||
}
|
||||
else {
|
||||
if (nullishSemantics === PredicateSemantics.Always) {
|
||||
error(leftTarget, Diagnostics.This_expression_is_always_nullish);
|
||||
}
|
||||
else {
|
||||
error(leftTarget, Diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish);
|
||||
}
|
||||
}
|
||||
checkNullishCoalesceOperandLeft(node);
|
||||
checkNullishCoalesceOperandRight(node);
|
||||
}
|
||||
}
|
||||
|
||||
function checkNullishCoalesceOperandLeft(node: BinaryExpression) {
|
||||
const leftTarget = skipOuterExpressions(node.left, OuterExpressionKinds.All);
|
||||
|
||||
const nullishSemantics = getSyntacticNullishnessSemantics(leftTarget);
|
||||
if (nullishSemantics !== PredicateSemantics.Sometimes) {
|
||||
if (nullishSemantics === PredicateSemantics.Always) {
|
||||
error(leftTarget, Diagnostics.This_expression_is_always_nullish);
|
||||
}
|
||||
else {
|
||||
error(leftTarget, Diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkNullishCoalesceOperandRight(node: BinaryExpression) {
|
||||
const rightTarget = skipOuterExpressions(node.right, OuterExpressionKinds.All);
|
||||
const nullishSemantics = getSyntacticNullishnessSemantics(rightTarget);
|
||||
if (isNotWithinNullishCoalesceExpression(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nullishSemantics === PredicateSemantics.Always) {
|
||||
error(rightTarget, Diagnostics.This_expression_is_always_nullish);
|
||||
}
|
||||
else if (nullishSemantics === PredicateSemantics.Never) {
|
||||
error(rightTarget, Diagnostics.This_expression_is_never_nullish);
|
||||
}
|
||||
}
|
||||
|
||||
function isNotWithinNullishCoalesceExpression(node: BinaryExpression) {
|
||||
return !isBinaryExpression(node.parent) || node.parent.operatorToken.kind !== SyntaxKind.QuestionQuestionToken;
|
||||
}
|
||||
|
||||
function getSyntacticNullishnessSemantics(node: Node): PredicateSemantics {
|
||||
node = skipOuterExpressions(node);
|
||||
switch (node.kind) {
|
||||
|
||||
@ -3987,6 +3987,10 @@
|
||||
"category": "Error",
|
||||
"code": 2880
|
||||
},
|
||||
"This expression is never nullish.": {
|
||||
"category": "Error",
|
||||
"code": 2881
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -1,39 +1,61 @@
|
||||
predicateSemantics.ts(7,16): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(10,16): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(26,12): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(27,12): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(28,12): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(29,12): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(30,12): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(33,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(34,11): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(35,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(36,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(51,14): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(52,14): error TS2695: Left side of comma operator is unused and has no side effects.
|
||||
predicateSemantics.ts(52,14): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(70,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(71,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(26,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(27,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(28,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(29,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(30,13): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(31,13): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(32,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(33,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(34,22): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(36,20): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(37,20): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(38,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(39,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(40,29): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(41,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(42,20): error TS2881: This expression is never nullish.
|
||||
predicateSemantics.ts(43,21): error TS2881: This expression is never nullish.
|
||||
predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(45,21): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(45,29): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(46,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(46,21): error TS2881: This expression is never nullish.
|
||||
predicateSemantics.ts(47,13): error TS2871: This expression is always nullish.
|
||||
predicateSemantics.ts(47,22): error TS2881: This expression is never nullish.
|
||||
predicateSemantics.ts(50,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(51,11): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(52,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(53,8): error TS2872: This kind of expression is always truthy.
|
||||
predicateSemantics.ts(70,14): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(71,14): error TS2695: Left side of comma operator is unused and has no side effects.
|
||||
predicateSemantics.ts(71,14): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(89,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
|
||||
|
||||
==== predicateSemantics.ts (16 errors) ====
|
||||
declare let cond: any;
|
||||
==== predicateSemantics.ts (38 errors) ====
|
||||
declare let opt: number | undefined;
|
||||
|
||||
// OK: One or other operand is possibly nullish
|
||||
const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
const test1 = (opt ? undefined : 32) ?? "possibly reached";
|
||||
|
||||
// Not OK: Both operands nullish
|
||||
const test2 = (cond ? undefined : null) ?? "always reached";
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
const test2 = (opt ? undefined : null) ?? "always reached";
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
|
||||
// Not OK: Both operands non-nullish
|
||||
const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
~~~~~~~~~~~~~~~
|
||||
const test3 = (opt ? 132 : 17) ?? "unreachable";
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
|
||||
// Parens
|
||||
const test4 = (cond ? (undefined) : (17)) ?? 42;
|
||||
const test4 = (opt ? (undefined) : (17)) ?? 42;
|
||||
|
||||
// Should be OK (special case)
|
||||
if (!!true) {
|
||||
@ -46,21 +68,82 @@ predicateSemantics.ts(71,1): error TS2869: Right operand of ?? is unreachable be
|
||||
while (true) { }
|
||||
while (false) { }
|
||||
|
||||
const p5 = {} ?? null;
|
||||
~~
|
||||
const p01 = {} ?? null;
|
||||
~~
|
||||
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
const p6 = 0 > 1 ?? null;
|
||||
~~~~~
|
||||
const p02 = 0 > 1 ?? null;
|
||||
~~~~~
|
||||
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
|
||||
const p7 = null ?? null;
|
||||
~~~~
|
||||
const p03 = null ?? 1;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p8 = (class foo { }) && null;
|
||||
~~~~~~~~~~~~~~~
|
||||
const p04 = null ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p05 = (class foo { }) && null;
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2872: This kind of expression is always truthy.
|
||||
const p9 = (class foo { }) || null;
|
||||
~~~~~~~~~~~~~~~
|
||||
const p06 = (class foo { }) || null;
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2872: This kind of expression is always truthy.
|
||||
const p07 = null ?? null ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p08 = null ?? opt ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p09 = null ?? (opt ? null : undefined) ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
|
||||
const p10 = opt ?? null ?? 1;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p11 = opt ?? null ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p12 = opt ?? (null ?? 1);
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p13 = opt ?? (null ?? null);
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p14 = opt ?? (null ?? null ?? null);
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p15 = opt ?? (opt ? null : undefined) ?? null;
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p16 = opt ?? 1 ?? 2;
|
||||
~
|
||||
!!! error TS2881: This expression is never nullish.
|
||||
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2881: This expression is never nullish.
|
||||
|
||||
const p21 = null ?? null ?? null ?? null;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
const p22 = null ?? 1 ?? 1;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~
|
||||
!!! error TS2881: This expression is never nullish.
|
||||
const p23 = null ?? (opt ? 1 : 2) ?? 1;
|
||||
~~~~
|
||||
!!! error TS2871: This expression is always nullish.
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2881: This expression is never nullish.
|
||||
|
||||
// Outer expression tests
|
||||
while ({} as any) { }
|
||||
@ -76,6 +159,8 @@ predicateSemantics.ts(71,1): error TS2869: Right operand of ?? is unreachable be
|
||||
~~~~~~
|
||||
!!! error TS2872: This kind of expression is always truthy.
|
||||
|
||||
declare let cond: any;
|
||||
|
||||
// Should be OK
|
||||
console.log((cond || undefined) && 1 / cond);
|
||||
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
//// [tests/cases/compiler/predicateSemantics.ts] ////
|
||||
|
||||
//// [predicateSemantics.ts]
|
||||
declare let cond: any;
|
||||
declare let opt: number | undefined;
|
||||
|
||||
// OK: One or other operand is possibly nullish
|
||||
const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
const test1 = (opt ? undefined : 32) ?? "possibly reached";
|
||||
|
||||
// Not OK: Both operands nullish
|
||||
const test2 = (cond ? undefined : null) ?? "always reached";
|
||||
const test2 = (opt ? undefined : null) ?? "always reached";
|
||||
|
||||
// Not OK: Both operands non-nullish
|
||||
const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
const test3 = (opt ? 132 : 17) ?? "unreachable";
|
||||
|
||||
// Parens
|
||||
const test4 = (cond ? (undefined) : (17)) ?? 42;
|
||||
const test4 = (opt ? (undefined) : (17)) ?? 42;
|
||||
|
||||
// Should be OK (special case)
|
||||
if (!!true) {
|
||||
@ -26,11 +26,28 @@ while (1) { }
|
||||
while (true) { }
|
||||
while (false) { }
|
||||
|
||||
const p5 = {} ?? null;
|
||||
const p6 = 0 > 1 ?? null;
|
||||
const p7 = null ?? null;
|
||||
const p8 = (class foo { }) && null;
|
||||
const p9 = (class foo { }) || null;
|
||||
const p01 = {} ?? null;
|
||||
const p02 = 0 > 1 ?? null;
|
||||
const p03 = null ?? 1;
|
||||
const p04 = null ?? null;
|
||||
const p05 = (class foo { }) && null;
|
||||
const p06 = (class foo { }) || null;
|
||||
const p07 = null ?? null ?? null;
|
||||
const p08 = null ?? opt ?? null;
|
||||
const p09 = null ?? (opt ? null : undefined) ?? null;
|
||||
|
||||
const p10 = opt ?? null ?? 1;
|
||||
const p11 = opt ?? null ?? null;
|
||||
const p12 = opt ?? (null ?? 1);
|
||||
const p13 = opt ?? (null ?? null);
|
||||
const p14 = opt ?? (null ?? null ?? null);
|
||||
const p15 = opt ?? (opt ? null : undefined) ?? null;
|
||||
const p16 = opt ?? 1 ?? 2;
|
||||
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
|
||||
|
||||
const p21 = null ?? null ?? null ?? null;
|
||||
const p22 = null ?? 1 ?? 1;
|
||||
const p23 = null ?? (opt ? 1 : 2) ?? 1;
|
||||
|
||||
// Outer expression tests
|
||||
while ({} as any) { }
|
||||
@ -38,6 +55,8 @@ while ({} satisfies unknown) { }
|
||||
while ((<any>({}))) { }
|
||||
while ((({}))) { }
|
||||
|
||||
declare let cond: any;
|
||||
|
||||
// Should be OK
|
||||
console.log((cond || undefined) && 1 / cond);
|
||||
|
||||
@ -79,15 +98,15 @@ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cook
|
||||
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
||||
return cooked;
|
||||
};
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
||||
// OK: One or other operand is possibly nullish
|
||||
var test1 = (_a = (cond ? undefined : 32)) !== null && _a !== void 0 ? _a : "possibly reached";
|
||||
var test1 = (_a = (opt ? undefined : 32)) !== null && _a !== void 0 ? _a : "possibly reached";
|
||||
// Not OK: Both operands nullish
|
||||
var test2 = (_b = (cond ? undefined : null)) !== null && _b !== void 0 ? _b : "always reached";
|
||||
var test2 = (_b = (opt ? undefined : null)) !== null && _b !== void 0 ? _b : "always reached";
|
||||
// Not OK: Both operands non-nullish
|
||||
var test3 = (_c = (cond ? 132 : 17)) !== null && _c !== void 0 ? _c : "unreachable";
|
||||
var test3 = (_c = (opt ? 132 : 17)) !== null && _c !== void 0 ? _c : "unreachable";
|
||||
// Parens
|
||||
var test4 = (_d = (cond ? (undefined) : (17))) !== null && _d !== void 0 ? _d : 42;
|
||||
var test4 = (_d = (opt ? (undefined) : (17))) !== null && _d !== void 0 ? _d : 42;
|
||||
// Should be OK (special case)
|
||||
if (!!true) {
|
||||
}
|
||||
@ -96,19 +115,34 @@ while (0) { }
|
||||
while (1) { }
|
||||
while (true) { }
|
||||
while (false) { }
|
||||
var p5 = (_e = {}) !== null && _e !== void 0 ? _e : null;
|
||||
var p6 = (_f = 0 > 1) !== null && _f !== void 0 ? _f : null;
|
||||
var p7 = null !== null && null !== void 0 ? null : null;
|
||||
var p8 = (/** @class */ (function () {
|
||||
var p01 = (_e = {}) !== null && _e !== void 0 ? _e : null;
|
||||
var p02 = (_f = 0 > 1) !== null && _f !== void 0 ? _f : null;
|
||||
var p03 = null !== null && null !== void 0 ? null : 1;
|
||||
var p04 = null !== null && null !== void 0 ? null : null;
|
||||
var p05 = (/** @class */ (function () {
|
||||
function foo() {
|
||||
}
|
||||
return foo;
|
||||
}())) && null;
|
||||
var p9 = (/** @class */ (function () {
|
||||
var p06 = (/** @class */ (function () {
|
||||
function foo() {
|
||||
}
|
||||
return foo;
|
||||
}())) || null;
|
||||
var p07 = (_g = null !== null && null !== void 0 ? null : null) !== null && _g !== void 0 ? _g : null;
|
||||
var p08 = (_h = null !== null && null !== void 0 ? null : opt) !== null && _h !== void 0 ? _h : null;
|
||||
var p09 = (_j = null !== null && null !== void 0 ? null : (opt ? null : undefined)) !== null && _j !== void 0 ? _j : null;
|
||||
var p10 = (_k = opt !== null && opt !== void 0 ? opt : null) !== null && _k !== void 0 ? _k : 1;
|
||||
var p11 = (_l = opt !== null && opt !== void 0 ? opt : null) !== null && _l !== void 0 ? _l : null;
|
||||
var p12 = opt !== null && opt !== void 0 ? opt : (null !== null && null !== void 0 ? null : 1);
|
||||
var p13 = opt !== null && opt !== void 0 ? opt : (null !== null && null !== void 0 ? null : null);
|
||||
var p14 = opt !== null && opt !== void 0 ? opt : ((_m = null !== null && null !== void 0 ? null : null) !== null && _m !== void 0 ? _m : null);
|
||||
var p15 = (_o = opt !== null && opt !== void 0 ? opt : (opt ? null : undefined)) !== null && _o !== void 0 ? _o : null;
|
||||
var p16 = (_p = opt !== null && opt !== void 0 ? opt : 1) !== null && _p !== void 0 ? _p : 2;
|
||||
var p17 = (_q = opt !== null && opt !== void 0 ? opt : (opt ? 1 : 2)) !== null && _q !== void 0 ? _q : 3;
|
||||
var p21 = (_s = (_r = null !== null && null !== void 0 ? null : null) !== null && _r !== void 0 ? _r : null) !== null && _s !== void 0 ? _s : null;
|
||||
var p22 = (_t = null !== null && null !== void 0 ? null : 1) !== null && _t !== void 0 ? _t : 1;
|
||||
var p23 = (_u = null !== null && null !== void 0 ? null : (opt ? 1 : 2)) !== null && _u !== void 0 ? _u : 1;
|
||||
// Outer expression tests
|
||||
while ({}) { }
|
||||
while ({}) { }
|
||||
@ -124,9 +158,9 @@ function foo() {
|
||||
{
|
||||
var maybe = null;
|
||||
var i = 0;
|
||||
var d = (_g = (i++, maybe)) !== null && _g !== void 0 ? _g : true; // ok
|
||||
var e = (_h = (i++, i++)) !== null && _h !== void 0 ? _h : true; // error
|
||||
var f = (_j = (maybe, i++)) !== null && _j !== void 0 ? _j : true; // error
|
||||
var d = (_v = (i++, maybe)) !== null && _v !== void 0 ? _v : true; // ok
|
||||
var e = (_w = (i++, i++)) !== null && _w !== void 0 ? _w : true; // error
|
||||
var f = (_x = (maybe, i++)) !== null && _x !== void 0 ? _x : true; // error
|
||||
}
|
||||
// https://github.com/microsoft/TypeScript/issues/60439
|
||||
var X = /** @class */ (function () {
|
||||
@ -137,6 +171,6 @@ var X = /** @class */ (function () {
|
||||
}
|
||||
return X;
|
||||
}());
|
||||
(_k = tag(__makeTemplateObject(["foo", ""], ["foo", ""]), 1)) !== null && _k !== void 0 ? _k : 32; // ok
|
||||
(_l = "foo".concat(1)) !== null && _l !== void 0 ? _l : 32; // error
|
||||
(_y = tag(__makeTemplateObject(["foo", ""], ["foo", ""]), 1)) !== null && _y !== void 0 ? _y : 32; // ok
|
||||
(_z = "foo".concat(1)) !== null && _z !== void 0 ? _z : 32; // error
|
||||
"foo" !== null && "foo" !== void 0 ? "foo" : 32; // error
|
||||
|
||||
@ -1,30 +1,30 @@
|
||||
//// [tests/cases/compiler/predicateSemantics.ts] ////
|
||||
|
||||
=== predicateSemantics.ts ===
|
||||
declare let cond: any;
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
declare let opt: number | undefined;
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
// OK: One or other operand is possibly nullish
|
||||
const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
const test1 = (opt ? undefined : 32) ?? "possibly reached";
|
||||
>test1 : Symbol(test1, Decl(predicateSemantics.ts, 3, 5))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// Not OK: Both operands nullish
|
||||
const test2 = (cond ? undefined : null) ?? "always reached";
|
||||
const test2 = (opt ? undefined : null) ?? "always reached";
|
||||
>test2 : Symbol(test2, Decl(predicateSemantics.ts, 6, 5))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// Not OK: Both operands non-nullish
|
||||
const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
const test3 = (opt ? 132 : 17) ?? "unreachable";
|
||||
>test3 : Symbol(test3, Decl(predicateSemantics.ts, 9, 5))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
// Parens
|
||||
const test4 = (cond ? (undefined) : (17)) ?? 42;
|
||||
const test4 = (opt ? (undefined) : (17)) ?? 42;
|
||||
>test4 : Symbol(test4, Decl(predicateSemantics.ts, 12, 5))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// Should be OK (special case)
|
||||
@ -38,22 +38,82 @@ while (1) { }
|
||||
while (true) { }
|
||||
while (false) { }
|
||||
|
||||
const p5 = {} ?? null;
|
||||
>p5 : Symbol(p5, Decl(predicateSemantics.ts, 25, 5))
|
||||
const p01 = {} ?? null;
|
||||
>p01 : Symbol(p01, Decl(predicateSemantics.ts, 25, 5))
|
||||
|
||||
const p6 = 0 > 1 ?? null;
|
||||
>p6 : Symbol(p6, Decl(predicateSemantics.ts, 26, 5))
|
||||
const p02 = 0 > 1 ?? null;
|
||||
>p02 : Symbol(p02, Decl(predicateSemantics.ts, 26, 5))
|
||||
|
||||
const p7 = null ?? null;
|
||||
>p7 : Symbol(p7, Decl(predicateSemantics.ts, 27, 5))
|
||||
const p03 = null ?? 1;
|
||||
>p03 : Symbol(p03, Decl(predicateSemantics.ts, 27, 5))
|
||||
|
||||
const p8 = (class foo { }) && null;
|
||||
>p8 : Symbol(p8, Decl(predicateSemantics.ts, 28, 5))
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 28, 12))
|
||||
const p04 = null ?? null;
|
||||
>p04 : Symbol(p04, Decl(predicateSemantics.ts, 28, 5))
|
||||
|
||||
const p9 = (class foo { }) || null;
|
||||
>p9 : Symbol(p9, Decl(predicateSemantics.ts, 29, 5))
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 29, 12))
|
||||
const p05 = (class foo { }) && null;
|
||||
>p05 : Symbol(p05, Decl(predicateSemantics.ts, 29, 5))
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 29, 13))
|
||||
|
||||
const p06 = (class foo { }) || null;
|
||||
>p06 : Symbol(p06, Decl(predicateSemantics.ts, 30, 5))
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 30, 13))
|
||||
|
||||
const p07 = null ?? null ?? null;
|
||||
>p07 : Symbol(p07, Decl(predicateSemantics.ts, 31, 5))
|
||||
|
||||
const p08 = null ?? opt ?? null;
|
||||
>p08 : Symbol(p08, Decl(predicateSemantics.ts, 32, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p09 = null ?? (opt ? null : undefined) ?? null;
|
||||
>p09 : Symbol(p09, Decl(predicateSemantics.ts, 33, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
const p10 = opt ?? null ?? 1;
|
||||
>p10 : Symbol(p10, Decl(predicateSemantics.ts, 35, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p11 = opt ?? null ?? null;
|
||||
>p11 : Symbol(p11, Decl(predicateSemantics.ts, 36, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p12 = opt ?? (null ?? 1);
|
||||
>p12 : Symbol(p12, Decl(predicateSemantics.ts, 37, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p13 = opt ?? (null ?? null);
|
||||
>p13 : Symbol(p13, Decl(predicateSemantics.ts, 38, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p14 = opt ?? (null ?? null ?? null);
|
||||
>p14 : Symbol(p14, Decl(predicateSemantics.ts, 39, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p15 = opt ?? (opt ? null : undefined) ?? null;
|
||||
>p15 : Symbol(p15, Decl(predicateSemantics.ts, 40, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
const p16 = opt ?? 1 ?? 2;
|
||||
>p16 : Symbol(p16, Decl(predicateSemantics.ts, 41, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
|
||||
>p17 : Symbol(p17, Decl(predicateSemantics.ts, 42, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
const p21 = null ?? null ?? null ?? null;
|
||||
>p21 : Symbol(p21, Decl(predicateSemantics.ts, 44, 5))
|
||||
|
||||
const p22 = null ?? 1 ?? 1;
|
||||
>p22 : Symbol(p22, Decl(predicateSemantics.ts, 45, 5))
|
||||
|
||||
const p23 = null ?? (opt ? 1 : 2) ?? 1;
|
||||
>p23 : Symbol(p23, Decl(predicateSemantics.ts, 46, 5))
|
||||
>opt : Symbol(opt, Decl(predicateSemantics.ts, 0, 11))
|
||||
|
||||
// Outer expression tests
|
||||
while ({} as any) { }
|
||||
@ -61,78 +121,81 @@ while ({} satisfies unknown) { }
|
||||
while ((<any>({}))) { }
|
||||
while ((({}))) { }
|
||||
|
||||
declare let cond: any;
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 54, 11))
|
||||
|
||||
// Should be OK
|
||||
console.log((cond || undefined) && 1 / cond);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 54, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
|
||||
>cond : Symbol(cond, Decl(predicateSemantics.ts, 54, 11))
|
||||
|
||||
function foo(this: Object | undefined) {
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 38, 45))
|
||||
>this : Symbol(this, Decl(predicateSemantics.ts, 40, 13))
|
||||
>foo : Symbol(foo, Decl(predicateSemantics.ts, 57, 45))
|
||||
>this : Symbol(this, Decl(predicateSemantics.ts, 59, 13))
|
||||
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// Should be OK
|
||||
return this ?? 0;
|
||||
>this : Symbol(this, Decl(predicateSemantics.ts, 40, 13))
|
||||
>this : Symbol(this, Decl(predicateSemantics.ts, 59, 13))
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/60401
|
||||
{
|
||||
const maybe = null as true | null;
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 47, 7))
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 66, 7))
|
||||
|
||||
let i = 0;
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 48, 5))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 67, 5))
|
||||
|
||||
const d = (i++, maybe) ?? true; // ok
|
||||
>d : Symbol(d, Decl(predicateSemantics.ts, 49, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 48, 5))
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 47, 7))
|
||||
>d : Symbol(d, Decl(predicateSemantics.ts, 68, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 67, 5))
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 66, 7))
|
||||
|
||||
const e = (i++, i++) ?? true; // error
|
||||
>e : Symbol(e, Decl(predicateSemantics.ts, 50, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 48, 5))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 48, 5))
|
||||
>e : Symbol(e, Decl(predicateSemantics.ts, 69, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 67, 5))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 67, 5))
|
||||
|
||||
const f = (maybe, i++) ?? true; // error
|
||||
>f : Symbol(f, Decl(predicateSemantics.ts, 51, 7))
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 47, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 48, 5))
|
||||
>f : Symbol(f, Decl(predicateSemantics.ts, 70, 7))
|
||||
>maybe : Symbol(maybe, Decl(predicateSemantics.ts, 66, 7))
|
||||
>i : Symbol(i, Decl(predicateSemantics.ts, 67, 5))
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/60439
|
||||
class X {
|
||||
>X : Symbol(X, Decl(predicateSemantics.ts, 52, 1))
|
||||
>X : Symbol(X, Decl(predicateSemantics.ts, 71, 1))
|
||||
|
||||
constructor() {
|
||||
const p = new.target ?? 32;
|
||||
>p : Symbol(p, Decl(predicateSemantics.ts, 57, 9))
|
||||
>new.target : Symbol(X, Decl(predicateSemantics.ts, 52, 1))
|
||||
>target : Symbol(X, Decl(predicateSemantics.ts, 52, 1))
|
||||
>p : Symbol(p, Decl(predicateSemantics.ts, 76, 9))
|
||||
>new.target : Symbol(X, Decl(predicateSemantics.ts, 71, 1))
|
||||
>target : Symbol(X, Decl(predicateSemantics.ts, 71, 1))
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/60614
|
||||
declare function tag<T>(
|
||||
>tag : Symbol(tag, Decl(predicateSemantics.ts, 59, 1))
|
||||
>T : Symbol(T, Decl(predicateSemantics.ts, 62, 21))
|
||||
>tag : Symbol(tag, Decl(predicateSemantics.ts, 78, 1))
|
||||
>T : Symbol(T, Decl(predicateSemantics.ts, 81, 21))
|
||||
|
||||
strings: TemplateStringsArray,
|
||||
>strings : Symbol(strings, Decl(predicateSemantics.ts, 62, 24))
|
||||
>strings : Symbol(strings, Decl(predicateSemantics.ts, 81, 24))
|
||||
>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
...values: number[]
|
||||
>values : Symbol(values, Decl(predicateSemantics.ts, 63, 32))
|
||||
>values : Symbol(values, Decl(predicateSemantics.ts, 82, 32))
|
||||
|
||||
): T | null;
|
||||
>T : Symbol(T, Decl(predicateSemantics.ts, 62, 21))
|
||||
>T : Symbol(T, Decl(predicateSemantics.ts, 81, 21))
|
||||
|
||||
tag`foo${1}` ?? 32; // ok
|
||||
>tag : Symbol(tag, Decl(predicateSemantics.ts, 59, 1))
|
||||
>tag : Symbol(tag, Decl(predicateSemantics.ts, 78, 1))
|
||||
|
||||
`foo${1}` ?? 32; // error
|
||||
`foo` ?? 32; // error
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
//// [tests/cases/compiler/predicateSemantics.ts] ////
|
||||
|
||||
=== predicateSemantics.ts ===
|
||||
declare let cond: any;
|
||||
>cond : any
|
||||
> : ^^^
|
||||
declare let opt: number | undefined;
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
|
||||
// OK: One or other operand is possibly nullish
|
||||
const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
const test1 = (opt ? undefined : 32) ?? "possibly reached";
|
||||
>test1 : 32 | "possibly reached"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(cond ? undefined : 32) ?? "possibly reached" : 32 | "possibly reached"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(cond ? undefined : 32) : 32
|
||||
> : ^^
|
||||
>cond ? undefined : 32 : 32
|
||||
> : ^^
|
||||
>cond : any
|
||||
> : ^^^
|
||||
>(opt ? undefined : 32) ?? "possibly reached" : 32 | "possibly reached"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(opt ? undefined : 32) : 32
|
||||
> : ^^
|
||||
>opt ? undefined : 32 : 32
|
||||
> : ^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
>32 : 32
|
||||
@ -25,34 +25,34 @@ const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
> : ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
// Not OK: Both operands nullish
|
||||
const test2 = (cond ? undefined : null) ?? "always reached";
|
||||
const test2 = (opt ? undefined : null) ?? "always reached";
|
||||
>test2 : "always reached"
|
||||
> : ^^^^^^^^^^^^^^^^
|
||||
>(cond ? undefined : null) ?? "always reached" : "always reached"
|
||||
> : ^^^^^^^^^^^^^^^^
|
||||
>(cond ? undefined : null) : null
|
||||
> : ^^^^
|
||||
>cond ? undefined : null : null
|
||||
> : ^^^^
|
||||
>cond : any
|
||||
> : ^^^
|
||||
>(opt ? undefined : null) ?? "always reached" : "always reached"
|
||||
> : ^^^^^^^^^^^^^^^^
|
||||
>(opt ? undefined : null) : null
|
||||
> : ^^^^
|
||||
>opt ? undefined : null : null
|
||||
> : ^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
>"always reached" : "always reached"
|
||||
> : ^^^^^^^^^^^^^^^^
|
||||
|
||||
// Not OK: Both operands non-nullish
|
||||
const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
const test3 = (opt ? 132 : 17) ?? "unreachable";
|
||||
>test3 : 132 | 17 | "unreachable"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(cond ? 132 : 17) ?? "unreachable" : 132 | 17 | "unreachable"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(cond ? 132 : 17) : 132 | 17
|
||||
> : ^^^^^^^^
|
||||
>cond ? 132 : 17 : 132 | 17
|
||||
> : ^^^^^^^^
|
||||
>cond : any
|
||||
> : ^^^
|
||||
>(opt ? 132 : 17) ?? "unreachable" : 132 | 17 | "unreachable"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(opt ? 132 : 17) : 132 | 17
|
||||
> : ^^^^^^^^
|
||||
>opt ? 132 : 17 : 132 | 17
|
||||
> : ^^^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>132 : 132
|
||||
> : ^^^
|
||||
>17 : 17
|
||||
@ -61,17 +61,17 @@ const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
// Parens
|
||||
const test4 = (cond ? (undefined) : (17)) ?? 42;
|
||||
const test4 = (opt ? (undefined) : (17)) ?? 42;
|
||||
>test4 : 17 | 42
|
||||
> : ^^^^^^^
|
||||
>(cond ? (undefined) : (17)) ?? 42 : 17 | 42
|
||||
> : ^^^^^^^
|
||||
>(cond ? (undefined) : (17)) : 17
|
||||
> : ^^
|
||||
>cond ? (undefined) : (17) : 17
|
||||
> : ^^
|
||||
>cond : any
|
||||
> : ^^^
|
||||
>(opt ? (undefined) : (17)) ?? 42 : 17 | 42
|
||||
> : ^^^^^^^
|
||||
>(opt ? (undefined) : (17)) : 17
|
||||
> : ^^
|
||||
>opt ? (undefined) : (17) : 17
|
||||
> : ^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(undefined) : undefined
|
||||
> : ^^^^^^^^^
|
||||
>undefined : undefined
|
||||
@ -111,17 +111,17 @@ while (false) { }
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
const p5 = {} ?? null;
|
||||
>p5 : {}
|
||||
> : ^^
|
||||
const p01 = {} ?? null;
|
||||
>p01 : {}
|
||||
> : ^^
|
||||
>{} ?? null : {}
|
||||
> : ^^
|
||||
>{} : {}
|
||||
> : ^^
|
||||
|
||||
const p6 = 0 > 1 ?? null;
|
||||
>p6 : boolean
|
||||
> : ^^^^^^^
|
||||
const p02 = 0 > 1 ?? null;
|
||||
>p02 : boolean
|
||||
> : ^^^^^^^
|
||||
>0 > 1 ?? null : boolean
|
||||
> : ^^^^^^^
|
||||
>0 > 1 : boolean
|
||||
@ -131,15 +131,23 @@ const p6 = 0 > 1 ?? null;
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const p7 = null ?? null;
|
||||
>p7 : any
|
||||
> : ^^^
|
||||
const p03 = null ?? 1;
|
||||
>p03 : 1
|
||||
> : ^
|
||||
>null ?? 1 : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const p04 = null ?? null;
|
||||
>p04 : any
|
||||
> : ^^^
|
||||
>null ?? null : null
|
||||
> : ^^^^
|
||||
|
||||
const p8 = (class foo { }) && null;
|
||||
>p8 : any
|
||||
> : ^^^
|
||||
const p05 = (class foo { }) && null;
|
||||
>p05 : any
|
||||
> : ^^^
|
||||
>(class foo { }) && null : null
|
||||
> : ^^^^
|
||||
>(class foo { }) : typeof foo
|
||||
@ -149,9 +157,9 @@ const p8 = (class foo { }) && null;
|
||||
>foo : typeof foo
|
||||
> : ^^^^^^^^^^
|
||||
|
||||
const p9 = (class foo { }) || null;
|
||||
>p9 : typeof foo
|
||||
> : ^^^^^^^^^^
|
||||
const p06 = (class foo { }) || null;
|
||||
>p06 : typeof foo
|
||||
> : ^^^^^^^^^^
|
||||
>(class foo { }) || null : typeof foo
|
||||
> : ^^^^^^^^^^
|
||||
>(class foo { }) : typeof foo
|
||||
@ -161,6 +169,198 @@ const p9 = (class foo { }) || null;
|
||||
>foo : typeof foo
|
||||
> : ^^^^^^^^^^
|
||||
|
||||
const p07 = null ?? null ?? null;
|
||||
>p07 : any
|
||||
> : ^^^
|
||||
>null ?? null ?? null : null
|
||||
> : ^^^^
|
||||
>null ?? null : null
|
||||
> : ^^^^
|
||||
|
||||
const p08 = null ?? opt ?? null;
|
||||
>p08 : number
|
||||
> : ^^^^^^
|
||||
>null ?? opt ?? null : number
|
||||
> : ^^^^^^
|
||||
>null ?? opt : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
|
||||
const p09 = null ?? (opt ? null : undefined) ?? null;
|
||||
>p09 : any
|
||||
> : ^^^
|
||||
>null ?? (opt ? null : undefined) ?? null : null
|
||||
> : ^^^^
|
||||
>null ?? (opt ? null : undefined) : null
|
||||
> : ^^^^
|
||||
>(opt ? null : undefined) : null
|
||||
> : ^^^^
|
||||
>opt ? null : undefined : null
|
||||
> : ^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
const p10 = opt ?? null ?? 1;
|
||||
>p10 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? null ?? 1 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? null : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const p11 = opt ?? null ?? null;
|
||||
>p11 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? null ?? null : number
|
||||
> : ^^^^^^
|
||||
>opt ?? null : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
|
||||
const p12 = opt ?? (null ?? 1);
|
||||
>p12 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (null ?? 1) : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(null ?? 1) : 1
|
||||
> : ^
|
||||
>null ?? 1 : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const p13 = opt ?? (null ?? null);
|
||||
>p13 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (null ?? null) : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(null ?? null) : null
|
||||
> : ^^^^
|
||||
>null ?? null : null
|
||||
> : ^^^^
|
||||
|
||||
const p14 = opt ?? (null ?? null ?? null);
|
||||
>p14 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (null ?? null ?? null) : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(null ?? null ?? null) : null
|
||||
> : ^^^^
|
||||
>null ?? null ?? null : null
|
||||
> : ^^^^
|
||||
>null ?? null : null
|
||||
> : ^^^^
|
||||
|
||||
const p15 = opt ?? (opt ? null : undefined) ?? null;
|
||||
>p15 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (opt ? null : undefined) ?? null : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (opt ? null : undefined) : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(opt ? null : undefined) : null
|
||||
> : ^^^^
|
||||
>opt ? null : undefined : null
|
||||
> : ^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
const p16 = opt ?? 1 ?? 2;
|
||||
>p16 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? 1 ?? 2 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? 1 : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
|
||||
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
|
||||
>p17 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (opt ? 1 : 2) ?? 3 : number
|
||||
> : ^^^^^^
|
||||
>opt ?? (opt ? 1 : 2) : number
|
||||
> : ^^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>(opt ? 1 : 2) : 1 | 2
|
||||
> : ^^^^^
|
||||
>opt ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
>3 : 3
|
||||
> : ^
|
||||
|
||||
const p21 = null ?? null ?? null ?? null;
|
||||
>p21 : any
|
||||
> : ^^^
|
||||
>null ?? null ?? null ?? null : null
|
||||
> : ^^^^
|
||||
>null ?? null ?? null : null
|
||||
> : ^^^^
|
||||
>null ?? null : null
|
||||
> : ^^^^
|
||||
|
||||
const p22 = null ?? 1 ?? 1;
|
||||
>p22 : 1
|
||||
> : ^
|
||||
>null ?? 1 ?? 1 : 1
|
||||
> : ^
|
||||
>null ?? 1 : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const p23 = null ?? (opt ? 1 : 2) ?? 1;
|
||||
>p23 : 1 | 2
|
||||
> : ^^^^^
|
||||
>null ?? (opt ? 1 : 2) ?? 1 : 1 | 2
|
||||
> : ^^^^^
|
||||
>null ?? (opt ? 1 : 2) : 1 | 2
|
||||
> : ^^^^^
|
||||
>(opt ? 1 : 2) : 1 | 2
|
||||
> : ^^^^^
|
||||
>opt ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>opt : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
// Outer expression tests
|
||||
while ({} as any) { }
|
||||
>{} as any : any
|
||||
@ -192,6 +392,10 @@ while ((({}))) { }
|
||||
>{} : {}
|
||||
> : ^^
|
||||
|
||||
declare let cond: any;
|
||||
>cond : any
|
||||
> : ^^^
|
||||
|
||||
// Should be OK
|
||||
console.log((cond || undefined) && 1 / cond);
|
||||
>console.log((cond || undefined) && 1 / cond) : void
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
declare let cond: any;
|
||||
declare let opt: number | undefined;
|
||||
|
||||
// OK: One or other operand is possibly nullish
|
||||
const test1 = (cond ? undefined : 32) ?? "possibly reached";
|
||||
const test1 = (opt ? undefined : 32) ?? "possibly reached";
|
||||
|
||||
// Not OK: Both operands nullish
|
||||
const test2 = (cond ? undefined : null) ?? "always reached";
|
||||
const test2 = (opt ? undefined : null) ?? "always reached";
|
||||
|
||||
// Not OK: Both operands non-nullish
|
||||
const test3 = (cond ? 132 : 17) ?? "unreachable";
|
||||
const test3 = (opt ? 132 : 17) ?? "unreachable";
|
||||
|
||||
// Parens
|
||||
const test4 = (cond ? (undefined) : (17)) ?? 42;
|
||||
const test4 = (opt ? (undefined) : (17)) ?? 42;
|
||||
|
||||
// Should be OK (special case)
|
||||
if (!!true) {
|
||||
@ -23,11 +23,28 @@ while (1) { }
|
||||
while (true) { }
|
||||
while (false) { }
|
||||
|
||||
const p5 = {} ?? null;
|
||||
const p6 = 0 > 1 ?? null;
|
||||
const p7 = null ?? null;
|
||||
const p8 = (class foo { }) && null;
|
||||
const p9 = (class foo { }) || null;
|
||||
const p01 = {} ?? null;
|
||||
const p02 = 0 > 1 ?? null;
|
||||
const p03 = null ?? 1;
|
||||
const p04 = null ?? null;
|
||||
const p05 = (class foo { }) && null;
|
||||
const p06 = (class foo { }) || null;
|
||||
const p07 = null ?? null ?? null;
|
||||
const p08 = null ?? opt ?? null;
|
||||
const p09 = null ?? (opt ? null : undefined) ?? null;
|
||||
|
||||
const p10 = opt ?? null ?? 1;
|
||||
const p11 = opt ?? null ?? null;
|
||||
const p12 = opt ?? (null ?? 1);
|
||||
const p13 = opt ?? (null ?? null);
|
||||
const p14 = opt ?? (null ?? null ?? null);
|
||||
const p15 = opt ?? (opt ? null : undefined) ?? null;
|
||||
const p16 = opt ?? 1 ?? 2;
|
||||
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
|
||||
|
||||
const p21 = null ?? null ?? null ?? null;
|
||||
const p22 = null ?? 1 ?? 1;
|
||||
const p23 = null ?? (opt ? 1 : 2) ?? 1;
|
||||
|
||||
// Outer expression tests
|
||||
while ({} as any) { }
|
||||
@ -35,6 +52,8 @@ while ({} satisfies unknown) { }
|
||||
while ((<any>({}))) { }
|
||||
while ((({}))) { }
|
||||
|
||||
declare let cond: any;
|
||||
|
||||
// Should be OK
|
||||
console.log((cond || undefined) && 1 / cond);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user