Don’t error for missing await when promise is referenced in condition body (#43593)

This commit is contained in:
Andrew Branch
2021-04-13 12:15:48 -07:00
committed by GitHub
parent d6012219e0
commit 06a73655d0
12 changed files with 326 additions and 83 deletions

View File

@@ -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)) {

View File

@@ -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
},

View File

@@ -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,

View File

@@ -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({

View File

@@ -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<any>) {
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

View File

@@ -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;

View File

@@ -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();

View File

@@ -1,24 +1,52 @@
tests/cases/compiler/truthinessPromiseCoercion.ts(5,9): error TS2801: This condition will always return true since this 'Promise<number>' appears to always be defined.
tests/cases/compiler/truthinessPromiseCoercion.ts(9,5): error TS2801: This condition will always return true since this 'Promise<number>' appears to always be defined.
tests/cases/compiler/truthinessPromiseCoercion.ts(6,9): error TS2801: This condition will always return true since this 'Promise<number>' is always defined.
tests/cases/compiler/truthinessPromiseCoercion.ts(10,5): error TS2801: This condition will always return true since this 'Promise<number>' is always defined.
tests/cases/compiler/truthinessPromiseCoercion.ts(31,9): error TS2801: This condition will always return true since this 'Promise<unknown>' is always defined.
==== tests/cases/compiler/truthinessPromiseCoercion.ts (2 errors) ====
==== tests/cases/compiler/truthinessPromiseCoercion.ts (3 errors) ====
declare const p: Promise<number>
declare const p2: null | Promise<number>
declare const obj: { p: Promise<unknown> }
async function f() {
if (p) {} // err
~
!!! error TS2801: This condition will always return true since this 'Promise<number>' 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<number>' 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<number>' 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<number>' 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<unknown>' 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
}

View File

@@ -1,6 +1,7 @@
//// [truthinessPromiseCoercion.ts]
declare const p: Promise<number>
declare const p2: null | Promise<number>
declare const obj: { p: Promise<unknown> }
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
}

View File

@@ -7,8 +7,13 @@ declare const p2: null | Promise<number>
>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<unknown> }
>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))
}

View File

@@ -6,6 +6,10 @@ declare const p2: null | Promise<number>
>p2 : Promise<number> | null
>null : null
declare const obj: { p: Promise<unknown> }
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
async function f() {
>f : () => Promise<void>
@@ -53,3 +57,78 @@ async function f() {
>arguments : any
}
// all ok
async function g() {
>g : () => Promise<void>
if (p) {
>p : Promise<number>
p;
>p : Promise<number>
}
if (p && p.then.length) {}
>p && p.then.length : number
>p : Promise<number>
>p.then.length : number
>p.then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
>p : Promise<number>
>then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
>length : number
if (p) {
>p : Promise<number>
if (p) {
>p : Promise<number>
if (p) {
>p : Promise<number>
!!await (((((((p)))))));
>!!await (((((((p))))))) : boolean
>!await (((((((p))))))) : boolean
>await (((((((p))))))) : number
>(((((((p))))))) : Promise<number>
>((((((p)))))) : Promise<number>
>(((((p))))) : Promise<number>
>((((p)))) : Promise<number>
>(((p))) : Promise<number>
>((p)) : Promise<number>
>(p) : Promise<number>
>p : Promise<number>
}
}
}
}
async function h() {
>h : () => Promise<void>
if (obj.p) {} // error
>obj.p : Promise<unknown>
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
if (obj.p) { // ok
>obj.p : Promise<unknown>
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
await obj.p;
>await obj.p : unknown
>obj.p : Promise<unknown>
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
}
if (obj.p && await obj.p) {} // ok
>obj.p && await obj.p : unknown
>obj.p : Promise<unknown>
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
>await obj.p : unknown
>obj.p : Promise<unknown>
>obj : { p: Promise<unknown>; }
>p : Promise<unknown>
}

View File

@@ -3,6 +3,7 @@
declare const p: Promise<number>
declare const p2: null | Promise<number>
declare const obj: { p: Promise<unknown> }
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
}