diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 781afe2cf9a84..45cde77aa5077 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35371,15 +35371,6 @@ namespace ts { if (!strictNullChecks) return; if (getFalsyFlags(type)) return; - if (getAwaitedTypeOfPromise(type)) { - errorAndMaybeSuggestAwait( - condExpr, - /*maybeMissingAwait*/ true, - Diagnostics.This_condition_will_always_return_true_since_this_0_appears_to_always_be_defined, - getTypeNameForErrorDisplay(type)); - return; - } - const location = isBinaryExpression(condExpr) ? condExpr.right : condExpr; const testedNode = isIdentifier(location) ? location : isPropertyAccessExpression(location) ? location.name @@ -35392,12 +35383,13 @@ namespace ts { } // While it technically should be invalid for any known-truthy value - // to be tested, we de-scope to functions unrefenced in the block as a - // heuristic to identify the most common bugs. There are too many - // false positives for values sourced from type definitions without - // strictNullChecks otherwise. + // to be tested, we de-scope to functions and Promises unreferenced in + // the block as a heuristic to identify the most common bugs. There + // are too many false positives for values sourced from type + // definitions without strictNullChecks otherwise. const callSignatures = getSignaturesOfType(type, SignatureKind.Call); - if (callSignatures.length === 0) { + const isPromise = !!getAwaitedTypeOfPromise(type); + if (callSignatures.length === 0 && !isPromise) { return; } @@ -35406,14 +35398,23 @@ namespace ts { return; } - const isUsed = isBinaryExpression(condExpr.parent) && isFunctionUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) - || body && isFunctionUsedInConditionBody(condExpr, body, testedNode, testedSymbol); + const isUsed = isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) + || body && isSymbolUsedInConditionBody(condExpr, body, testedNode, testedSymbol); if (!isUsed) { - error(location, Diagnostics.This_condition_will_always_return_true_since_this_function_appears_to_always_be_defined_Did_you_mean_to_call_it_instead); + if (isPromise) { + errorAndMaybeSuggestAwait( + location, + /*maybeMissingAwait*/ true, + Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined, + getTypeNameForErrorDisplay(type)); + } + else { + error(location, Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead); + } } } - function isFunctionUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean { + function isSymbolUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean { return !!forEachChild(body, function check(childNode): boolean | undefined { if (isIdentifier(childNode)) { const childSymbol = getSymbolAtLocation(childNode); @@ -35451,7 +35452,7 @@ namespace ts { }); } - function isFunctionUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean { + function isSymbolUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean { while (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { const isUsed = forEachChild(node.right, function visit(child): boolean | undefined { if (isIdentifier(child)) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6a5765f4a9bab..270c1b7da3437 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3172,7 +3172,7 @@ "category": "Error", "code": 2773 }, - "This condition will always return true since this function appears to always be defined. Did you mean to call it instead?": { + "This condition will always return true since this function is always defined. Did you mean to call it instead?": { "category": "Error", "code": 2774 }, @@ -3280,7 +3280,7 @@ "category": "Error", "code": 2800 }, - "This condition will always return true since this '{0}' appears to always be defined.": { + "This condition will always return true since this '{0}' is always defined.": { "category": "Error", "code": 2801 }, diff --git a/src/services/codefixes/addMissingAwait.ts b/src/services/codefixes/addMissingAwait.ts index a31bf50f46ea3..e3a15d8864144 100644 --- a/src/services/codefixes/addMissingAwait.ts +++ b/src/services/codefixes/addMissingAwait.ts @@ -14,7 +14,7 @@ namespace ts.codefix { Diagnostics.Operator_0_cannot_be_applied_to_type_1.code, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2.code, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap.code, - Diagnostics.This_condition_will_always_return_true_since_this_0_appears_to_always_be_defined.code, + Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined.code, Diagnostics.Type_0_is_not_an_array_type.code, Diagnostics.Type_0_is_not_an_array_type_or_a_string_type.code, Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators.code, diff --git a/src/services/codefixes/fixMissingCallParentheses.ts b/src/services/codefixes/fixMissingCallParentheses.ts index 042f7b506c7d5..e86aa129aa40b 100644 --- a/src/services/codefixes/fixMissingCallParentheses.ts +++ b/src/services/codefixes/fixMissingCallParentheses.ts @@ -2,7 +2,7 @@ namespace ts.codefix { const fixId = "fixMissingCallParentheses"; const errorCodes = [ - Diagnostics.This_condition_will_always_return_true_since_this_function_appears_to_always_be_defined_Did_you_mean_to_call_it_instead.code, + Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead.code, ]; registerCodeFix({ diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt index 132738e4ac1fe..d9645dc64922a 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt @@ -1,17 +1,17 @@ -tests/cases/compiler/truthinessCallExpressionCoercion.ts(2,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(18,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(36,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(50,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(66,13): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(76,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(2,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(18,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(36,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(50,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(66,13): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(76,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? ==== tests/cases/compiler/truthinessCallExpressionCoercion.ts (7 errors) ==== function onlyErrorsWhenTestingNonNullableFunctionType(required: () => boolean, optional?: () => boolean) { if (required) { // error ~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } if (optional) { // ok @@ -29,7 +29,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th if (test) { // error ~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? console.log('test'); } @@ -49,7 +49,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th if (test) { // error ~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? [() => null].forEach(test => { test(); }); @@ -65,7 +65,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th if (x.foo.bar) { // error ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } if (x.foo.bar) { // ok @@ -83,7 +83,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th test() { if (this.isUser) { // error ~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } if (this.maybeIsUser) { // ok @@ -95,7 +95,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th function A(stats: StatsBase) { if (stats.isDirectory) { // err ~~~~~~~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? console.log(`[Directory] ${stats.ctime}`) } } @@ -103,7 +103,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th function B(a: Nested, b: Nested) { if (a.stats.isDirectory) { // err ~~~~~~~~~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? b.stats.isDirectory(); } if (a.stats.isDirectory) { // ok diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt index 4c041935cde8f..ae4486bc5937a 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt @@ -1,8 +1,8 @@ -tests/cases/compiler/truthinessCallExpressionCoercion1.ts(3,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion1.ts(19,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion1.ts(33,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion1.ts(46,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion1.ts(3,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion1.ts(19,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion1.ts(33,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion1.ts(46,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? ==== tests/cases/compiler/truthinessCallExpressionCoercion1.ts (5 errors) ==== @@ -10,7 +10,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // error required ? console.log('required') : undefined; ~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok optional ? console.log('optional') : undefined; @@ -28,7 +28,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // error test ? console.log('test') : undefined; ~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok test ? console.log(test) : undefined; @@ -44,7 +44,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // error test ~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? ? [() => null].forEach(test => { test() }) : undefined; } @@ -59,7 +59,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // error x.foo.bar ? console.log('x.foo.bar') : undefined; ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok x.foo.bar ? x.foo.bar : undefined; @@ -91,7 +91,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // error this.isUser ? console.log('this.isUser') : undefined; ~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok this.maybeIsUser ? console.log('this.maybeIsUser') : undefined; diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt index d744718a8de45..9c6978b92b365 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt @@ -1,14 +1,14 @@ -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(11,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(14,10): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(41,18): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(44,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(48,11): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(65,46): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(76,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(79,10): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(99,5): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(109,9): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? -tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(11,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(14,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(41,18): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(44,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(48,11): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(65,46): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(76,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(79,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(99,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(109,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? ==== tests/cases/compiler/truthinessCallExpressionCoercion2.ts (11 errors) ==== @@ -24,12 +24,12 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: // error required1 && console.log('required'); ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // error 1 && required1 && console.log('required'); ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok required1 && required1(); @@ -58,18 +58,18 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: // error required1 && required2 && required1() && console.log('foo'); ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // error if (required1 && b) { ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } // error if (((required1 && b))) { ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } // ok @@ -88,7 +88,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: typeof window !== 'undefined' && window.console && ((window.console as any).firebug || (window.console.exception && window.console.table)); ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } function checksPropertyAccess() { @@ -101,12 +101,12 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: // error x.foo.bar && console.log('x.foo.bar'); ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // error 1 && x.foo.bar && console.log('x.foo.bar'); ~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok x.foo.bar && x.foo.bar(); @@ -128,7 +128,7 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: // error x1.a.b.c && x2.a.b.c(); ~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? } class Foo { @@ -140,12 +140,12 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: // error this.required && console.log('required'); ~~~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // error 1 && this.required && console.log('required'); ~~~~~~~~~~~~~ -!!! error TS2774: This condition will always return true since this function appears to always be defined. Did you mean to call it instead? +!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? // ok this.required && this.required(); diff --git a/tests/baselines/reference/truthinessPromiseCoercion.errors.txt b/tests/baselines/reference/truthinessPromiseCoercion.errors.txt index aaba8031475d6..cacbacfe4ff40 100644 --- a/tests/baselines/reference/truthinessPromiseCoercion.errors.txt +++ b/tests/baselines/reference/truthinessPromiseCoercion.errors.txt @@ -1,24 +1,52 @@ -tests/cases/compiler/truthinessPromiseCoercion.ts(5,9): error TS2801: This condition will always return true since this 'Promise' appears to always be defined. -tests/cases/compiler/truthinessPromiseCoercion.ts(9,5): error TS2801: This condition will always return true since this 'Promise' appears to always be defined. +tests/cases/compiler/truthinessPromiseCoercion.ts(6,9): error TS2801: This condition will always return true since this 'Promise' is always defined. +tests/cases/compiler/truthinessPromiseCoercion.ts(10,5): error TS2801: This condition will always return true since this 'Promise' is always defined. +tests/cases/compiler/truthinessPromiseCoercion.ts(31,9): error TS2801: This condition will always return true since this 'Promise' is always defined. -==== tests/cases/compiler/truthinessPromiseCoercion.ts (2 errors) ==== +==== tests/cases/compiler/truthinessPromiseCoercion.ts (3 errors) ==== declare const p: Promise declare const p2: null | Promise + declare const obj: { p: Promise } async function f() { if (p) {} // err ~ -!!! error TS2801: This condition will always return true since this 'Promise' appears to always be defined. -!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:5:9: Did you forget to use 'await'? +!!! error TS2801: This condition will always return true since this 'Promise' is always defined. +!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:6:9: Did you forget to use 'await'? if (!!p) {} // no err if (p2) {} // no err p ? f.arguments : f.arguments; ~ -!!! error TS2801: This condition will always return true since this 'Promise' appears to always be defined. -!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:9:5: Did you forget to use 'await'? +!!! error TS2801: This condition will always return true since this 'Promise' is always defined. +!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:10:5: Did you forget to use 'await'? !!p ? f.arguments : f.arguments; p2 ? f.arguments : f.arguments; } + + // all ok + async function g() { + if (p) { + p; + } + if (p && p.then.length) {} + if (p) { + if (p) { + if (p) { + !!await (((((((p))))))); + } + } + } + } + + async function h() { + if (obj.p) {} // error + ~~~~~ +!!! error TS2801: This condition will always return true since this 'Promise' is always defined. +!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:31:9: Did you forget to use 'await'? + if (obj.p) { // ok + await obj.p; + } + if (obj.p && await obj.p) {} // ok + } \ No newline at end of file diff --git a/tests/baselines/reference/truthinessPromiseCoercion.js b/tests/baselines/reference/truthinessPromiseCoercion.js index 1333b4d1a680b..880adbd90cb47 100644 --- a/tests/baselines/reference/truthinessPromiseCoercion.js +++ b/tests/baselines/reference/truthinessPromiseCoercion.js @@ -1,6 +1,7 @@ //// [truthinessPromiseCoercion.ts] declare const p: Promise declare const p2: null | Promise +declare const obj: { p: Promise } async function f() { if (p) {} // err @@ -11,6 +12,29 @@ async function f() { !!p ? f.arguments : f.arguments; p2 ? f.arguments : f.arguments; } + +// all ok +async function g() { + if (p) { + p; + } + if (p && p.then.length) {} + if (p) { + if (p) { + if (p) { + !!await (((((((p))))))); + } + } + } +} + +async function h() { + if (obj.p) {} // error + if (obj.p) { // ok + await obj.p; + } + if (obj.p && await obj.p) {} // ok +} //// [truthinessPromiseCoercion.js] @@ -22,3 +46,24 @@ async function f() { !!p ? f.arguments : f.arguments; p2 ? f.arguments : f.arguments; } +// all ok +async function g() { + if (p) { + p; + } + if (p && p.then.length) { } + if (p) { + if (p) { + if (p) { + !!await (((((((p))))))); + } + } + } +} +async function h() { + if (obj.p) { } // error + if (obj.p) { // ok + await obj.p; + } + if (obj.p && await obj.p) { } // ok +} diff --git a/tests/baselines/reference/truthinessPromiseCoercion.symbols b/tests/baselines/reference/truthinessPromiseCoercion.symbols index 6e6639732485a..53301a2c856d6 100644 --- a/tests/baselines/reference/truthinessPromiseCoercion.symbols +++ b/tests/baselines/reference/truthinessPromiseCoercion.symbols @@ -7,8 +7,13 @@ declare const p2: null | Promise >p2 : Symbol(p2, Decl(truthinessPromiseCoercion.ts, 1, 13)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +declare const obj: { p: Promise } +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + async function f() { ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) if (p) {} // err >p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) @@ -22,28 +27,89 @@ async function f() { p ? f.arguments : f.arguments; >p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) !!p ? f.arguments : f.arguments; >p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) p2 ? f.arguments : f.arguments; >p2 : Symbol(p2, Decl(truthinessPromiseCoercion.ts, 1, 13)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) >f.arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) ->f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 1, 40)) +>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 2, 42)) >arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --)) } +// all ok +async function g() { +>g : Symbol(g, Decl(truthinessPromiseCoercion.ts, 12, 1)) + + if (p) { +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + + p; +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + } + if (p && p.then.length) {} +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) +>p.then.length : Symbol(Function.length, Decl(lib.es5.d.ts, --, --)) +>p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>length : Symbol(Function.length, Decl(lib.es5.d.ts, --, --)) + + if (p) { +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + + if (p) { +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + + if (p) { +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + + !!await (((((((p))))))); +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13)) + } + } + } +} + +async function h() { +>h : Symbol(h, Decl(truthinessPromiseCoercion.ts, 27, 1)) + + if (obj.p) {} // error +>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) + + if (obj.p) { // ok +>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) + + await obj.p; +>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) + } + if (obj.p && await obj.p) {} // ok +>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +>obj : Symbol(obj, Decl(truthinessPromiseCoercion.ts, 2, 13)) +>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20)) +} + diff --git a/tests/baselines/reference/truthinessPromiseCoercion.types b/tests/baselines/reference/truthinessPromiseCoercion.types index 1f41f7170b42c..3cc81c116b6ef 100644 --- a/tests/baselines/reference/truthinessPromiseCoercion.types +++ b/tests/baselines/reference/truthinessPromiseCoercion.types @@ -6,6 +6,10 @@ declare const p2: null | Promise >p2 : Promise | null >null : null +declare const obj: { p: Promise } +>obj : { p: Promise; } +>p : Promise + async function f() { >f : () => Promise @@ -53,3 +57,78 @@ async function f() { >arguments : any } +// all ok +async function g() { +>g : () => Promise + + if (p) { +>p : Promise + + p; +>p : Promise + } + if (p && p.then.length) {} +>p && p.then.length : number +>p : Promise +>p.then.length : number +>p.then : (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>p : Promise +>then : (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>length : number + + if (p) { +>p : Promise + + if (p) { +>p : Promise + + if (p) { +>p : Promise + + !!await (((((((p))))))); +>!!await (((((((p))))))) : boolean +>!await (((((((p))))))) : boolean +>await (((((((p))))))) : number +>(((((((p))))))) : Promise +>((((((p)))))) : Promise +>(((((p))))) : Promise +>((((p)))) : Promise +>(((p))) : Promise +>((p)) : Promise +>(p) : Promise +>p : Promise + } + } + } +} + +async function h() { +>h : () => Promise + + if (obj.p) {} // error +>obj.p : Promise +>obj : { p: Promise; } +>p : Promise + + if (obj.p) { // ok +>obj.p : Promise +>obj : { p: Promise; } +>p : Promise + + await obj.p; +>await obj.p : unknown +>obj.p : Promise +>obj : { p: Promise; } +>p : Promise + } + if (obj.p && await obj.p) {} // ok +>obj.p && await obj.p : unknown +>obj.p : Promise +>obj : { p: Promise; } +>p : Promise +>await obj.p : unknown +>obj.p : Promise +>obj : { p: Promise; } +>p : Promise +} + diff --git a/tests/cases/compiler/truthinessPromiseCoercion.ts b/tests/cases/compiler/truthinessPromiseCoercion.ts index b67e023d9ae3f..03feda55f20a8 100644 --- a/tests/cases/compiler/truthinessPromiseCoercion.ts +++ b/tests/cases/compiler/truthinessPromiseCoercion.ts @@ -3,6 +3,7 @@ declare const p: Promise declare const p2: null | Promise +declare const obj: { p: Promise } async function f() { if (p) {} // err @@ -13,3 +14,26 @@ async function f() { !!p ? f.arguments : f.arguments; p2 ? f.arguments : f.arguments; } + +// all ok +async function g() { + if (p) { + p; + } + if (p && p.then.length) {} + if (p) { + if (p) { + if (p) { + !!await (((((((p))))))); + } + } + } +} + +async function h() { + if (obj.p) {} // error + if (obj.p) { // ok + await obj.p; + } + if (obj.p && await obj.p) {} // ok +}