question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Why doesn't awaiting a Promise<never> change reachability?

See original GitHub issue

TypeScript Version: 3.7.2

Search Terms:

  • “Promise<never>”
  • await
  • reachability analysis
  • control flow analysis
  • definite assignment analysis

Code

(async () => {
    let b: string;
    let a1 = await Promise.reject(); // returns Promise<never>
    b = ""; // Not unreachable?
    b.toUpperCase(); // Not unreachable?
})();

Expected behavior: As a1 is inferred to be never (e.g. behaves like in the non-promised version), I expected the rest of the code to be marked as unreachable aswell:

function returnNever(): never { throw new Error(); }

(async () => {
    let b: string;
    let a0 = returnNever(); // a0 is never
    b = ""; // Unreachable
    b.toUpperCase(); // Unreachable
})();

Actual behavior: The code after the never-returning promise is marked as reachable.

Related Question on StackOverflow: Has more code: https://stackoverflow.com/questions/58732814 Related Issue: https://github.com/microsoft/TypeScript/issues/10973 (although marked as “Working as intended”, it was changed later. 3.7.2 behaves like the issue opener expected).

If this is not a bug, what is the background for this behavior?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:14
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
andrewbranchcommented, Dec 6, 2019

Yeah, since we actually error on unreachable code, this does seem worthy of the bug label.

1reaction
nikeeecommented, Dec 4, 2019

Consider a logErrorAsync function that returns Promise<never>. It awaits something and then throws an error on every path (or goes into an infinite loop etc.). If the function does not return a Promise<never> but a never instead, it behaves as expected.

As of TS 3.7.3:

declare function fetchB(): Promise<string>;

async function logErrorAsync(err: any): Promise<never> {
    await fetch("/foo/...");
    console.log("Error has been submitted to analytics tool");
    throw new Error(err);
}

function logError(err: any): never {
    console.error(err);
    throw new Error(err);
}

(async () => {
    let b: string;
    try {
        b = await fetchB();
    } catch (err) {
        await logErrorAsync(err); // awaiting Promise<never>
    }
    b.toUpperCase(); // "Error: "b" is used before assignment;" would require workarounds
})();

//...
(async () => {
    let b: string;
    try {
        b = await fetchB();
    } catch (err) {
        logError(err); // returns never
    }
    b.toUpperCase(); // No error, as expected
})();
Read more comments on GitHub >

github_iconTop Results From Across the Web

Why is Promise<never> not considered in reachability analysis?
It seems that there is a reason to not consider await s of Promise<never> -returning functions in any aspect of the control flow...
Read more >
await - JavaScript - MDN Web Docs
If the value is not a Promise , await converts the value to a resolved Promise , and waits for it. The awaited...
Read more >
javascript - await does not wait for Promise to finish
So it's a bit weird. The "waiting" happens within that aync function, not your initial js function. consider this example
Read more >
Issues · microsoft/TypeScript · GitHub
String literal rename doesn't work in object unions · #41489 opened Nov 11, 2020 ; Why doesn't awaiting a Promise<never> change reachability? ·...
Read more >
Asynchronous Programming - Eloquent JavaScript
But that doesn't help when we want a single program to be able to make progress while it is waiting for a network...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found