Detect missing await in TypeScript
Using promises in JavaScript/TypeScript is very common. More and more APIs use them, including the ones provided by the browser such as fetch or Service worker registration. Using the async/await syntax, promises are very convenient to use.
function delay(ms: number) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
async function simulateLongComputation() {
await delay(100);
return 42;
}
However, it's also very easy to forget awaiting a promise, mainly if you are refactoring your code. Even when you don't await a promise, the ts file is perfectly valid, so the TypeScript compiler can compile without error. But the code does not behave as expected. This pattern is called fire and forget because you start a promise but you'll never get the result of the promise (success or failure). This is not often what you want.
function checkValueAsync(value: any) {
return new Promise((resolve, reject) => {
if (value) {
resolve();
} else {
reject();
}
});
}
try {
checkValueAsync(null); // missing await here
} catch (ex) {
console.log(ex); // no error, because the promise is not awaited
}
The only information is an error in the console if the promise failed:
Google Chrome Developer tools error message
If you are familiar with C#, you know there is a compilation warning to prevent this mistake. The TypeScript compiler doesn't provide such an option. So, you have to use another solution. Since version 4.4, TSLint can check your code does not contain floating promises.
#Using TSLint to detect floating promises
TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors. It is widely supported across modern editors & build systems and can be customized with your own lint rules, configurations, and formatters.
Download TSLint:
npm install -g tslint typescript
Configure TSLint:
TSLint provides lots of rules. In this post, we'll only use the one to detect floating promises.
Create a file named
tslint.json
in the root directory of your project with the following content:JSON{ "extends": "tslint:recommended", "rules": { "no-floating-promises": true } }
Note: If you are using JQuery promises or any other alternative to standard promises, you have to adapt the configuration with something similar to:
"no-floating-promises": [true, "JQueryPromise"]
.Run tslint:
tslint --project tsconfig.json
PS F:\Samples> tslint --project tsconfig.json
ERROR: F:/Samples/index.ts[12, 5]: Promises must be handled appropriately
You can now easily detect where you forgot to await promises thanks to TSLint 😃
BTW, if you actually want the fire and forget behavior, you can disable the tslint rule for a specific line:
// tslint:disable-next-line:no-floating-promises
checkValueAsync(null);
Or you can change the return type of the statement using void
:
void checkValueAsync(null);
#Conclusion
TSLint is a valuable tool to add to your toolbox. You can easily integrate it into your build pipeline. In this post, I show only one rule of TSLint, but you can activate more than 100 rules to ensure your code is well-written!
#Additional resources
- TSLint: https://palantir.github.io/tslint/
- TSLint rules: https://palantir.github.io/tslint/rules/
- Gulp-TSLint: https://www.npmjs.com/package/gulp-tslint
- async/await: nowait keyword: https://github.com/microsoft/TypeScript/issues/13376
Do you have a question or a suggestion about this post? Contact me!