Skip to main content

await-thenable

Disallow awaiting a value that is not a Thenable.

💡

Some problems reported by this rule are manually fixable by editor suggestions.

💭

This rule requires type information to run.

A "Thenable" value is an object which has a then method, such as a Promise. The await keyword is generally used to retrieve the result of calling a Thenable's then method.

If the await keyword 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.

eslint.config.mjs
export default tseslint.config({
rules: {
"@typescript-eslint/await-thenable": "error"
}
});

Try this rule in the playground ↗

Examples

await 'value';

const createValue = () => 'value';
await createValue();
Open in Playground

Async Iteration (for await...of Loops)

This rule also inspects for await...of statements, and reports if the value being iterated over is not async-iterable.

Why does the rule report on for await...of loops used on an array of Promises?

While for await...of can 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...of and using for...of (apart from awaiting each result yourself) is error handling. When an error occurs within the loop body, for await...of does not close the original sync iterable, while for...of does. For detailed examples of this, see the MDN documentation on using for await...of with sync-iterables.

Also consider whether you need sequential awaiting at all. Using for await...of may obscure potential opportunities for concurrent processing, such as those reported by no-await-in-loop. Consider instead using one of the promise concurrency methods for better performance.

Examples

async 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 Playground

Explicit Resource Management (await using Statements)

This rule also inspects await using statements. If the disposable being used is not async-disposable, an await using statement is unnecessary.

Examples

function makeSyncDisposable(): Disposable {
return {
[Symbol.dispose](): void {
// Dispose of the resource
},
};
}

async function shouldNotAwait() {
await using resource = makeSyncDisposable();
}
Open in Playground

Options

This rule is not configurable.

When Not To Use It

If you want to allow code to await non-Promise values. For example, if your framework is in transition from one style of asynchronous code to another, it may be useful to include awaits 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.

See Troubleshooting > Linting with Type Information > Performance if you experience performance degradations after enabling type checked rules.

Resources