Microsoft/TypeScript

Incorrect use-before-declaration error in async IIFE initializer

Open

#50 123 ouverte le 1 août 2022

Voir sur GitHub
 (7 commentaires) (1 réaction) (0 assignés)TypeScript (6 726 forks)batch import
BugDomain: BinderHelp Wanted

Métriques du dépôt

Stars
 (48 455 stars)
Métriques de merge PR
 (Merge moyen 6j 17h) (9 PRs mergées en 30 j)

Description

Bug Report

🔎 Search Terms

  • dead zone
  • await tdz
  • use before declaration await

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about await

⏯ Playground Link

Playground link with relevant code

💻 Code

const promise = (async () => {
  await null
  promise
})()
  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])

🙁 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, awaiting 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.

Guide contributeur