Repository: TypeScript
Issue: Incorrect use-before-declaration error in async IIFE initializer
Labels: Bug,Help Wanted

# Bug Report

<!--
  Please fill in each section completely. Thank you!
-->

### 🔎 Search Terms

<!--
  What search terms did you use when trying to find an existing bug report?
  List them here so people in the future can find this one more easily.
-->

- dead zone
- await tdz
- use before declaration await

### 🕗 Version & Regression Information

<!-- When did you start seeing this bug occur?

"Bugs" that have existed in TS for a long time are very likely to be FAQs; refer to
  https://github.com/Microsoft/TypeScript/wiki/FAQ#common-bugs-that-arent-bugs

If possible, please try testing the nightly version of TS to see if it's already been fixed.
For npm: `typescript@next`
This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly

Note: The TypeScript Playground can be used to try older versions of TypeScript.

Please keep and fill in the line that best applies:
-->
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about await

### ⏯ Playground Link

<!--
  A link to a TypeScript Playground "Share" link which shows this behavior

  The TypeScript Workbench can be used for more complex setups, try
  https://www.typescriptlang.org/dev/bug-workbench/

  As a last resort, you can link to a repo, but these will be slower for us to investigate.
-->
[Playground link with relevant code](
https://www.typescriptlang.org/play?ts=4.8.0-dev.20220731#code/MYewdgzgLgBADgJxAWwJYQKYwLwwBQCGEAnmMPgJQ4B8MA3gLABQMMBA7garGAK4A2-Zq0Qp0GZgF8KeCsyA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
const promise = (async () => {
  await null
  promise
})()
```

<details>
<summary>Real life code sample affected by the error</summary>

```tsx
  useEffect(() => {
    const request = (async () => {
      try {
        const response = await premiumApi.announcements(client)
        // @ts-expect-error TypeScript bug, assumes "request" is still in dead zone after await
        if (pendingRequest.current === request || pendingRequest.current === undefined) {
          pendingRequest.current = undefined
          setApiResponse(response)
        }
      } catch {
        pendingRequest.current = undefined
      }
    })()
    pendingRequest.current = request
    return () => {
      pendingRequest.current = undefined
    }
  }, [client])
```

</details>

### 🙁 Actual behavior

- "Block-scoped variable 'promise' used before its declaration."
- "Variable 'promise' is used before being assigned."

### 🙂 Expected behavior

- No errors related to the `promise` variable.

This is not about the "'await' has no effect on the type of this expression" warning, this is a feature and is expected ~~despite me disagreeing with it~~.

The first `await` to be reached in an `async` function is the point where the function stops being synchronous and yields a `Promise` for its result. This means that, immediately after the `await`, the `const promise` is no longer in TDZ and is well-defined: it is the not-yet-resolved `Promise` that was produced by the IIFE's invocation. Now, `await`ing the `promise` _would_ be a deadlock, as the promise would now be waiting for itself to resolve before being able to resolve, but the `Promise` instance itself is still useful for some purposes like `===` checks.