Description
π Search Terms
"promise", "dangling promise", "async", "floating promise"
β Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
β Suggestion
I think it would be valuable for TypeScript to have an option enabling stricter checks on async functions and promises. Things like:
- Disallowing promises that aren't handled or awaited
- Disallowing async functions to stand in for functions that are clearly expected to be synchronous. A common bug we run into is passing async functions into
Array.forEach()
:
async function foo() {
["foo.txt", "bar.txt"].forEach(async (path) {
const contents = await fs.readFile(path);
}); // returns immediately, instead of waiting until all files are read!
}
1) is currently handled by https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-floating-promises.md.
2) isn't handled by any common tooling that I'm aware of.
Promises and async/await are common patterns used in JavaScript, and there are a whole class of possible bugs that could be eliminated from stricter TypeScript checking. Some of these are currently handled by third-party linters like ESLint, but misuse of promises are so common, and so likely to be bugs, that I think they deserve to be brought into TypeScript as compile errors. Another benefit is that it prevents users from having to run 2 different tools, each constructing their own ASTs, to get compile-time safety.
To avoid breaking existing TypeScript code, we could gate this change behind a flag for users to decide when/if to opt in.
π Motivating Example
Stricter handling of promises to avoid writing bugs in async code.
Note these kind of checks exist in other statically typed languages and type checkers, such as:
π» Use Cases
What do you want to use this for?
Detect entire classes of common async bugs at compile time.
What shortcomings exist with current approaches?
ESLint has a no-floating-promises rule, but it's slow and sometimes has buggy false negatives.
What workarounds are you using in the meantime?
ESLint