Skip to main content

no-misused-promises

Disallow Promises in places not designed to handle them.

💭

This rule requires type information to run.

This rule forbids providing Promises to logical locations such as if statements in places where the TypeScript compiler allows them but they are not handled properly. These situations can often arise due to a missing await keyword or just a misunderstanding of the way async functions are handled/awaited.

tip

no-misused-promises only detects code that provides Promises to incorrect logical locations. See no-floating-promises for detecting unhandled Promise statements.

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

Try this rule in the playground ↗

Options

This rule accepts the following options:

type Options = [
{
/** Whether to warn when a Promise is provided to conditional statements. */
checksConditionals?: boolean;
/** Whether to warn when `...` spreading a `Promise`. */
checksSpreads?: boolean;
/** Whether to warn when a Promise is returned from a function typed as returning `void`. */
checksVoidReturn?: /**
* Whether to warn when a Promise is returned from a function typed as returning `void`.
* Whether to disable checking all asynchronous functions.
*/
| boolean
/** Which forms of functions may have checking disabled. */
| {
/** Disables checking an asynchronous function passed as argument where the parameter type expects a function that returns `void`. */
arguments?: boolean;
/** Disables checking an asynchronous function passed as a JSX attribute expected to be a function that returns `void`. */
attributes?: boolean;
/** Disables checking an asynchronous method in a type that extends or implements another type expecting that method to return `void`. */
inheritedMethods?: boolean;
/** Disables checking an asynchronous function passed as an object property expected to be a function that returns `void`. */
properties?: boolean;
/** Disables checking an asynchronous function returned in a function whose return type is a function that returns `void`. */
returns?: boolean;
/** Disables checking an asynchronous function used as a variable whose return type is a function that returns `void`. */
variables?: boolean;
};
},
];

const defaultOptions: Options = [
{ checksConditionals: true, checksSpreads: true, checksVoidReturn: true },
];

checksConditionals

Whether to warn when a Promise is provided to conditional statements. Default: true.

If you don't want to check conditionals, you can configure the rule with "checksConditionals": false:

{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksConditionals": false
}
]
}

Doing so prevents the rule from looking at code like if (somePromise).

checksVoidReturn

Whether to warn when a Promise is returned from a function typed as returning void. Default: true.

Likewise, if you don't want to check functions that return promises where a void return is expected, your configuration will look like this:

{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": false
}
]
}

You can disable selective parts of the checksVoidReturn option by providing an object that disables specific checks. For example, if you don't mind that passing a () => Promise<void> to a () => void parameter or JSX attribute can lead to a floating unhandled Promise:

{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": {
"arguments": false,
"attributes": false
}
}
]
}

The following sub-options are supported:

arguments

Disables checking an asynchronous function passed as argument where the parameter type expects a function that returns void.

attributes

Disables checking an asynchronous function passed as a JSX attribute expected to be a function that returns void.

inheritedMethods

Disables checking an asynchronous method in a type that extends or implements another type expecting that method to return void.

note

For now, no-misused-promises only checks named methods against extended/implemented types: that is, call/construct/index signatures are ignored. Call signatures are not required in TypeScript to be consistent with one another, and construct signatures cannot be async in the first place. Index signature checking may be implemented in the future.

properties

Disables checking an asynchronous function passed as an object property expected to be a function that returns void.

returns

Disables checking an asynchronous function returned in a function whose return type is a function that returns void.

variables

Disables checking an asynchronous function used as a variable whose return type is a function that returns void.

checksSpreads

Whether to warn when ... spreading a Promise. Default: true.

If you don't want to check object spreads, you can add this configuration:

{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksSpreads": false
}
]
}

Examples

checksConditionals

Examples of code for this rule with checksConditionals: true:

const promise = Promise.resolve('value');

if (promise) {
// Do something
}

const val = promise ? 123 : 456;

[1, 2, 3].filter(() => promise);

while (promise) {
// Do something
}
Open in Playground

checksVoidReturn

Examples of code for this rule with checksVoidReturn: true:

[1, 2, 3].forEach(async value => {
await fetch(`/${value}`);
});

new Promise<void>(async (resolve, reject) => {
await fetch('/');
resolve();
});

document.addEventListener('click', async () => {
console.log('synchronous call');
await fetch('/');
console.log('synchronous call');
});

interface MySyncInterface {
setThing(): void;
}
class MyClass implements MySyncInterface {
async setThing(): Promise<void> {
this.thing = await fetchThing();
}
}
Open in Playground

checksSpreads

Examples of code for this rule with checksSpreads: true:

const getData = () => fetch('/');

console.log({ foo: 42, ...getData() });

const awaitData = async () => {
await fetch('/');
};

console.log({ foo: 42, ...awaitData() });
Open in Playground

When Not To Use It

This rule can be difficult to enable on large existing projects that set up many misused Promises. Alternately, if you're not worried about crashes from floating or misused Promises -such as if you have global unhandled Promise handlers registered- then in some cases it may be safe to not use this rule. You might consider using ESLint disable comments for those specific situations instead of completely disabling this rule.

Further Reading


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