Skip to main content

no-misused-promises

Disallow Promises in places not designed to handle them.

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.

Attributes

  • Included in configs
    • ✅ Recommended
    • 🔒 Strict
  • Fixable
    • 🔧 Automated Fixer
    • 🛠 Suggestion Fixer
  • 💭 Requires type information

Rule Details

This rule accepts a single option which is an object with checksConditionals, checksVoidReturn, and checksSpreads properties indicating which types of misuse to flag. All are enabled by default.

Options

type Options = [
{
checksConditionals?: boolean;
checksVoidReturn?: boolean | ChecksVoidReturnOptions;
checksSpreads?: boolean;
},
];

interface ChecksVoidReturnOptions {
arguments?: boolean;
attributes?: boolean;
properties?: boolean;
returns?: boolean;
variables?: boolean;
}

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

"checksConditionals"

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"

Likewise, if you don't want functions that return promises where a void return is expected to be checked, 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. The following 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
  • 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

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
}
}
]
}

"checksSpreads"

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

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

checksConditionals: true

Examples of code for this rule with checksConditionals: true:

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

if (promise) {
// Do something
}

const val = promise ? 123 : 456;

while (promise) {
// Do something
}

checksVoidReturn: true

Examples of code for this rule with checksVoidReturn: true:

[1, 2, 3].forEach(async value => {
await doSomething(value);
});

new Promise(async (resolve, reject) => {
await doSomething();
resolve();
});

const eventEmitter = new EventEmitter();
eventEmitter.on('some-event', async () => {
synchronousCall();
await doSomething();
otherSynchronousCall();
});

checksSpreads: true

Examples of code for this rule with checksSpreads: true:

const getData = () => someAsyncOperation({ myArg: 'foo' });

return { foo: 42, ...getData() };

const getData2 = async () => {
await someAsyncOperation({ myArg: 'foo' });
};

return { foo: 42, ...getData2() };

When Not To Use It

If you do not use Promises in your codebase or are not concerned with possible misuses of them outside of what the TypeScript compiler will check.

Further Reading