await-thenable
Disallow awaiting a value that is not a Thenable.
✅Extending
"plugin:@typescript-eslint/ recommended-type-checked "in an ESLint configuration enables this rule.💡Some problems reported by this rule are manually fixable by editor suggestions .
💭This rule requires type information to run, which comes with performance tradeoffs.
A "Thenable" value is an object which has a
thenmethod, such as a Promise. Theawaitkeyword is generally used to retrieve the result of calling a Thenable'sthenmethod.If the
awaitkeyword is used on a value that is not a Thenable, the value is directly resolved, but will still pause execution until the next microtask. While doing so is valid JavaScript, it is often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise.
- Flat Config
- Legacy Config
eslint.config.mjsexport default defineConfig({
rules: {
"@typescript-eslint/await-thenable": "error"
}
});.eslintrc.cjsmodule.exports = {
"rules": {
"@typescript-eslint/await-thenable": "error"
}
};Try this rule in the playground ↗
Examples
- ❌ Incorrect
- ✅ Correct
Open in Playgroundawait 'value';
const createValue = () => 'value';
await createValue();
Open in Playgroundawait Promise.resolve('value');
const createValue = async () => 'value';
await createValue();Async Iteration (
for await...ofLoops) This rule also inspects
for await...ofstatements , and reports if the value being iterated over is not async-iterable.Why does the rule report onfor await...ofloops used on an array of Promises?While
for await...ofcan be used with synchronous iterables, and it will await each promise produced by the iterable, it is inadvisable to do so. There are some tiny nuances that you may want to consider.The biggest difference between using
for await...ofand usingfor...of(apart from awaiting each result yourself) is error handling. When an error occurs within the loop body,for await...ofdoes not close the original sync iterable, whilefor...ofdoes. For detailed examples of this, see the MDN documentation on usingfor await...ofwith sync-iterables .Also consider whether you need sequential awaiting at all. Using
for await...ofmay obscure potential opportunities for concurrent processing, such as those reported byno-await-in-loop. Consider instead using one of the promise concurrency methods for better performance.Examples
- ❌ Incorrect
- ✅ Correct
Open in Playgroundasync function syncIterable() {
const arrayOfValues = [1, 2, 3];
for await (const value of arrayOfValues) {
console.log(value);
}
}
async function syncIterableOfPromises() {
const arrayOfPromises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
for await (const promisedValue of arrayOfPromises) {
console.log(promisedValue);
}
}Open in Playgroundasync function syncIterable() {
const arrayOfValues = [1, 2, 3];
for (const value of arrayOfValues) {
console.log(value);
}
}
async function syncIterableOfPromises( ) {
const arrayOfPromises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
for (const promisedValue of await Promise.all(arrayOfPromises)) {
console.log(promisedValue);
}
}
async function validUseOfForAwaitOnAsyncIterable() {
async function* yieldThingsAsynchronously() {
yield 1;
await new Promise(resolve => setTimeout(resolve, 1000));
yield 2;
}
for await (const promisedValue of yieldThingsAsynchronously()) {
console.log(promisedValue);
}
}Explicit Resource Management (
await usingStatements) This rule also inspects
await usingstatements . If the disposable being used is not async-disposable, anawait usingstatement is unnecessary.Examples
- ❌ Incorrect
- ✅ Correct
Open in Playgroundfunction makeSyncDisposable(): Disposable {
return {
[Symbol.dispose](): void {
// Dispose of the resource
},
};
}
async function shouldNotAwait() {
await using resource = makeSyncDisposable();
}Open in Playgroundfunction makeSyncDisposable(): Disposable {
return {
[Symbol.dispose](): void {
// Dispose of the resource
},
};
}
async function shouldNotAwait() {
using resource = makeSyncDisposable();
}
function makeAsyncDisposable(): AsyncDisposable {
return {
async [Symbol.asyncDispose](): Promise<void> {
// Dispose of the resource asynchronously
},
};
}
async function shouldAwait() {
await using resource = makeAsyncDisposable();
}Options
This rule is not configurable.
When Not To Use It
If you want to allow code to
awaitnon-Promise values. For example, if your framework is in transition from one style of asynchronous code to another, it may be useful to includeawaits unnecessarily. This is generally not preferred but can sometimes be useful for visual consistency. You might consider using ESLint disable comments for those specific situations instead of completely disabling this rule.Type checked lint rules are more powerful than traditional lint rules, but also require configuring type checked linting .