mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Issue unawaited promise error on symbol-less expressions (#44491)
* Issue unawaited promise error on symbol-less expressions
* Use same behavior for call expressions
* Revert "Use same behavior for call expressions"
This reverts commit 60d58132e4.
This commit is contained in:
@@ -35870,15 +35870,14 @@ namespace ts {
|
||||
if (getFalsyFlags(type)) return;
|
||||
|
||||
const location = isBinaryExpression(condExpr) ? condExpr.right : condExpr;
|
||||
if (isPropertyAccessExpression(location) && isAssertionExpression(skipParentheses(location.expression))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const testedNode = isIdentifier(location) ? location
|
||||
: isPropertyAccessExpression(location) ? location.name
|
||||
: isBinaryExpression(location) && isIdentifier(location.right) ? location.right
|
||||
: undefined;
|
||||
const isPropertyExpressionCast = isPropertyAccessExpression(location)
|
||||
&& isAssertionExpression(skipParentheses(location.expression));
|
||||
if (!testedNode || isPropertyExpressionCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
// While it technically should be invalid for any known-truthy value
|
||||
// to be tested, we de-scope to functions and Promises unreferenced in
|
||||
@@ -35891,13 +35890,13 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
const testedSymbol = getSymbolAtLocation(testedNode);
|
||||
if (!testedSymbol) {
|
||||
const testedSymbol = testedNode && getSymbolAtLocation(testedNode);
|
||||
if (!testedSymbol && !isPromise) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isUsed = isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol)
|
||||
|| body && isSymbolUsedInConditionBody(condExpr, body, testedNode, testedSymbol);
|
||||
const isUsed = testedSymbol && isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol)
|
||||
|| testedSymbol && body && isSymbolUsedInConditionBody(condExpr, body, testedNode!, testedSymbol);
|
||||
if (!isUsed) {
|
||||
if (isPromise) {
|
||||
errorAndMaybeSuggestAwait(
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
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(7,9): error TS2801: This condition will always return true since this 'Promise<number>' is always defined.
|
||||
tests/cases/compiler/truthinessPromiseCoercion.ts(11,5): error TS2801: This condition will always return true since this 'Promise<number>' is always defined.
|
||||
tests/cases/compiler/truthinessPromiseCoercion.ts(32,9): error TS2801: This condition will always return true since this 'Promise<unknown>' is always defined.
|
||||
tests/cases/compiler/truthinessPromiseCoercion.ts(40,9): error TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.
|
||||
tests/cases/compiler/truthinessPromiseCoercion.ts(43,9): error TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.
|
||||
|
||||
|
||||
==== tests/cases/compiler/truthinessPromiseCoercion.ts (3 errors) ====
|
||||
==== tests/cases/compiler/truthinessPromiseCoercion.ts (5 errors) ====
|
||||
declare const p: Promise<number>
|
||||
declare const p2: null | Promise<number>
|
||||
declare const obj: { p: Promise<unknown> }
|
||||
declare function pf(): Promise<boolean>
|
||||
|
||||
async function f() {
|
||||
if (p) {} // err
|
||||
~
|
||||
!!! 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'?
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:7: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>' is always defined.
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:10:5: Did you forget to use 'await'?
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:11:5: Did you forget to use 'await'?
|
||||
!!p ? f.arguments : f.arguments;
|
||||
p2 ? f.arguments : f.arguments;
|
||||
}
|
||||
@@ -43,10 +46,26 @@ tests/cases/compiler/truthinessPromiseCoercion.ts(31,9): error TS2801: This cond
|
||||
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'?
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:32:9: Did you forget to use 'await'?
|
||||
if (obj.p) { // ok
|
||||
await obj.p;
|
||||
}
|
||||
if (obj.p && await obj.p) {} // ok
|
||||
}
|
||||
|
||||
async function i(): Promise<string> {
|
||||
if (pf()) { // error
|
||||
~~~~
|
||||
!!! error TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:40:9: Did you forget to use 'await'?
|
||||
return "true";
|
||||
}
|
||||
if (pf()) { // error
|
||||
~~~~
|
||||
!!! error TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.
|
||||
!!! related TS2773 tests/cases/compiler/truthinessPromiseCoercion.ts:43:9: Did you forget to use 'await'?
|
||||
pf().then();
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
declare const p: Promise<number>
|
||||
declare const p2: null | Promise<number>
|
||||
declare const obj: { p: Promise<unknown> }
|
||||
declare function pf(): Promise<boolean>
|
||||
|
||||
async function f() {
|
||||
if (p) {} // err
|
||||
@@ -35,6 +36,16 @@ async function h() {
|
||||
}
|
||||
if (obj.p && await obj.p) {} // ok
|
||||
}
|
||||
|
||||
async function i(): Promise<string> {
|
||||
if (pf()) { // error
|
||||
return "true";
|
||||
}
|
||||
if (pf()) { // error
|
||||
pf().then();
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
|
||||
//// [truthinessPromiseCoercion.js]
|
||||
@@ -67,3 +78,12 @@ async function h() {
|
||||
}
|
||||
if (obj.p && await obj.p) { } // ok
|
||||
}
|
||||
async function i() {
|
||||
if (pf()) { // error
|
||||
return "true";
|
||||
}
|
||||
if (pf()) { // error
|
||||
pf().then();
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
@@ -12,8 +12,12 @@ declare const obj: { p: Promise<unknown> }
|
||||
>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, --, --))
|
||||
|
||||
declare function pf(): Promise<boolean>
|
||||
>pf : Symbol(pf, Decl(truthinessPromiseCoercion.ts, 2, 42))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
|
||||
if (p) {} // err
|
||||
>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13))
|
||||
@@ -27,34 +31,34 @@ 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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>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, 2, 42))
|
||||
>f : Symbol(f, Decl(truthinessPromiseCoercion.ts, 3, 39))
|
||||
>arguments : Symbol(Function.arguments, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
||||
// all ok
|
||||
async function g() {
|
||||
>g : Symbol(g, Decl(truthinessPromiseCoercion.ts, 12, 1))
|
||||
>g : Symbol(g, Decl(truthinessPromiseCoercion.ts, 13, 1))
|
||||
|
||||
if (p) {
|
||||
>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 0, 13))
|
||||
@@ -87,7 +91,7 @@ async function g() {
|
||||
}
|
||||
|
||||
async function h() {
|
||||
>h : Symbol(h, Decl(truthinessPromiseCoercion.ts, 27, 1))
|
||||
>h : Symbol(h, Decl(truthinessPromiseCoercion.ts, 28, 1))
|
||||
|
||||
if (obj.p) {} // error
|
||||
>obj.p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20))
|
||||
@@ -113,3 +117,23 @@ async function h() {
|
||||
>p : Symbol(p, Decl(truthinessPromiseCoercion.ts, 2, 20))
|
||||
}
|
||||
|
||||
async function i(): Promise<string> {
|
||||
>i : Symbol(i, Decl(truthinessPromiseCoercion.ts, 36, 1))
|
||||
>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, --, --))
|
||||
|
||||
if (pf()) { // error
|
||||
>pf : Symbol(pf, Decl(truthinessPromiseCoercion.ts, 2, 42))
|
||||
|
||||
return "true";
|
||||
}
|
||||
if (pf()) { // error
|
||||
>pf : Symbol(pf, Decl(truthinessPromiseCoercion.ts, 2, 42))
|
||||
|
||||
pf().then();
|
||||
>pf().then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
|
||||
>pf : Symbol(pf, Decl(truthinessPromiseCoercion.ts, 2, 42))
|
||||
>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ declare const obj: { p: Promise<unknown> }
|
||||
>obj : { p: Promise<unknown>; }
|
||||
>p : Promise<unknown>
|
||||
|
||||
declare function pf(): Promise<boolean>
|
||||
>pf : () => Promise<boolean>
|
||||
|
||||
async function f() {
|
||||
>f : () => Promise<void>
|
||||
|
||||
@@ -132,3 +135,28 @@ async function h() {
|
||||
>p : Promise<unknown>
|
||||
}
|
||||
|
||||
async function i(): Promise<string> {
|
||||
>i : () => Promise<string>
|
||||
|
||||
if (pf()) { // error
|
||||
>pf() : Promise<boolean>
|
||||
>pf : () => Promise<boolean>
|
||||
|
||||
return "true";
|
||||
>"true" : "true"
|
||||
}
|
||||
if (pf()) { // error
|
||||
>pf() : Promise<boolean>
|
||||
>pf : () => Promise<boolean>
|
||||
|
||||
pf().then();
|
||||
>pf().then() : Promise<boolean>
|
||||
>pf().then : <TResult1 = boolean, TResult2 = never>(onfulfilled?: ((value: boolean) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
|
||||
>pf() : Promise<boolean>
|
||||
>pf : () => Promise<boolean>
|
||||
>then : <TResult1 = boolean, TResult2 = never>(onfulfilled?: ((value: boolean) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
|
||||
}
|
||||
return "false";
|
||||
>"false" : "false"
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
declare const p: Promise<number>
|
||||
declare const p2: null | Promise<number>
|
||||
declare const obj: { p: Promise<unknown> }
|
||||
declare function pf(): Promise<boolean>
|
||||
|
||||
async function f() {
|
||||
if (p) {} // err
|
||||
@@ -37,3 +38,13 @@ async function h() {
|
||||
}
|
||||
if (obj.p && await obj.p) {} // ok
|
||||
}
|
||||
|
||||
async function i(): Promise<string> {
|
||||
if (pf()) { // error
|
||||
return "true";
|
||||
}
|
||||
if (pf()) { // error
|
||||
pf().then();
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user