Repository: TypeScript
Issue: Extend the "forgot an await" check from 4.3 to do limited AST analysis to cover more cases
Labels: Suggestion,Experience Enhancement

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

Promise await async "Did you forget to use 'await'?"

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [X] This wouldn't change the runtime behavior of existing JavaScript code
* [X] This could be implemented without emitting different JS based on the types of the expressions
* [X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [X] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

The new [always-truthy promise checks](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3-rc/#truthy-promise-checks) are amazing!
They're very much like @typescript-eslint's [`no-misused-promises`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md).

As I was investigating https://github.com/typescript-eslint/typescript-eslint/issues/3403, one thing I noticed was that it looks like TypeScript does not do any AST interrogation for this feature - it just inspects the type of the expression.

It'd be great if we could extend this feature to do some AST traversal for common cases (logical expressions and ternaries) so that it can catch more errors.

To clarify what I'm asking for:
1) If an `IfStatement`'s `.expression` is a `BinaryExpression` and the `.operator` is one of `BarBarToken`, `AmpersandAmpersandToken`, or `QuestionQuestionToken`, then TypeScript should recursively check the `.left` and `.right` of the node.
2) if an `IfStatement`'s `.expression` is a `ConditionalExpression`, then TypeScript should recursively check the `.whenTrue` and `.whenFalse` of the node.

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

```ts
declare async function isValid(): Promise<boolean>;
declare const user: {isActive: boolean} | undefined;

// As of TS4.3
if (isValid()) {
//  ^^^^^^^^^
// This condition will always return true since this 'Promise<boolean>' appears to always be defined. (2801)
}
```

```ts
// with this proposal, the following would be an error as well:

if (user?.isActive && isValid()) {
//                    ^^^^^^^^^
}

if (user?.isActive || isValid()) {
//                    ^^^^^^^^^
}

if (user?.isActive ?? isValid()) {
//                    ^^^^^^^^^
}
```

```ts
if (user?.isActive ? isValid() : false) {
//                   ^^^^^^^^^
}
if (user?.isActive ? false : isValid()) {
//                           ^^^^^^^^^
}
if (
  user?.isActive
  ? someOtherCondition
  ? isValid()
//  ^^^^^^^^^
  : false
  : isValid()
//  ^^^^^^^^^
) {
}
```

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

The current approach is a step in the right direction, but it could cover even more cases!
Workaround is to use `@typescript-eslint/no-misused-promises` which does these in-depth checks.