Skip to main content

no-floating-promises

Require Promise-like statements to be handled appropriately.

💡

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

💭

This rule requires type information to run.

A "floating" Promise is one that is created without any code set up to handle any errors it might throw. Floating Promises can cause several issues, such as improperly sequenced operations, ignored Promise rejections, and more.

This rule will report Promise-valued statements that are not treated in one of the following ways:

  • Calling its .then() with two arguments
  • Calling its .catch() with one argument
  • awaiting it
  • returning it
  • voiding it

This rule also reports when an Array containing Promises is created and not properly handled. The main way to resolve this is by using one of the Promise concurrency methods to create a single Promise, then handling that according to the procedure above. These methods include:

  • Promise.all()
  • Promise.allSettled()
  • Promise.any()
  • Promise.race()
tip

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

See Using promises (error handling) on MDN for a detailed writeup on Promise error-handling.

.eslintrc.cjs
module.exports = {
"rules": {
"@typescript-eslint/no-floating-promises": "error"
}
};

Try this rule in the playground ↗

Examples

const promise = new Promise((resolve, reject) => resolve('value'));
promise;

async function returnsPromise() {
return 'value';
}
returnsPromise().then(() => {});

Promise.reject('value').catch();

Promise.reject('value').finally();

[1, 2, 3].map(async x => x + 1);
Open in Playground

Options

This rule accepts the following options:

type Options = [
{
/** Type specifiers of functions whose calls are safe to float. */
allowForKnownSafeCalls?: (
| {
from: 'file';
name: [string, ...string[]] | string;
path?: string;
}
| {
from: 'lib';
name: [string, ...string[]] | string;
}
| {
from: 'package';
name: [string, ...string[]] | string;
package: string;
}
| string
)[];
/** Type specifiers that are known to be safe to float. */
allowForKnownSafePromises?: (
| {
from: 'file';
name: [string, ...string[]] | string;
path?: string;
}
| {
from: 'lib';
name: [string, ...string[]] | string;
}
| {
from: 'package';
name: [string, ...string[]] | string;
package: string;
}
| string
)[];
/** Whether to check all "Thenable"s, not just the built-in Promise type. */
checkThenables?: boolean;
/** Whether to ignore async IIFEs (Immediately Invoked Function Expressions). */
ignoreIIFE?: boolean;
/** Whether to ignore `void` expressions. */
ignoreVoid?: boolean;
},
];

const defaultOptions: Options = [
{
allowForKnownSafeCalls: [],
allowForKnownSafePromises: [],
checkThenables: false,
ignoreIIFE: false,
ignoreVoid: true,
},
];

checkThenables

A "Thenable" value is an object which has a then method, such as a Promise. Other Thenables include TypeScript's built-in PromiseLike interface and any custom object that happens to have a .then().

The checkThenables option triggers no-floating-promises to also consider all values that satisfy the Thenable shape (a .then() method that takes two callback parameters), not just Promises. This can be useful if your code works with older Promise polyfills instead of the native Promise class.

declare function createPromiseLike(): PromiseLike<string>;

createPromiseLike();

interface MyThenable {
then(onFulfilled: () => void, onRejected: () => void): MyThenable;
}

declare function createMyThenable(): MyThenable;

createMyThenable();
Open in Playground

ignoreVoid

This option, which is true by default, allows you to stop the rule reporting promises consumed with the void operator. This can be a good way to explicitly mark a promise as intentionally not awaited.

warning

Voiding a Promise doesn't handle it or change the runtime behavior. The outcome is just ignored, like disabling the rule with an ESLint disable comment. Such Promise rejections will still be unhandled.

Examples of correct code for this rule with { ignoreVoid: true }:

async function returnsPromise() {
return 'value';
}
void returnsPromise();

void Promise.reject('value');
Open in Playground

With this option set to true, and if you are using no-void, you should turn on the allowAsStatement option.

ignoreIIFE

This allows you to skip checking of async IIFEs (Immediately Invoked Function Expressions).

Examples of correct code for this rule with { ignoreIIFE: true }:

await (async function () {
await res(1);
})();

(async function () {
await res(1);
})();
Open in Playground

allowForKnownSafePromises

Specific types to be marked as "safe" to be floating. For example, you may need to do this in the case of libraries whose APIs return Promises whose rejections are safely handled by the library.

This option takes the shared TypeOrValueSpecifier format.

Examples of code for this rule with:

{
"allowForKnownSafePromises": [
{ "from": "file", "name": "SafePromise" },
{ "from": "lib", "name": "PromiseLike" },
{ "from": "package", "name": "Bar", "package": "bar-lib" }
]
}
let promise: Promise<number> = Promise.resolve(2);
promise;

function returnsPromise(): Promise<number> {
return Promise.resolve(42);
}

returnsPromise();
Open in Playground

allowForKnownSafeCalls

Specific functions to be marked as "safe" to be called to create floating Promises. For example, you may need to do this in the case of libraries whose APIs may be called without handling the resultant Promises.

This option takes the shared TypeOrValueSpecifier format.

Examples of code for this rule with:

{
"allowForKnownSafeCalls": [
{ "from": "file", "name": "safe", "path": "input.ts" }
]
}
declare function unsafe(...args: unknown[]): Promise<void>;

unsafe('...', () => {});
Open in Playground

When Not To Use It

This rule can be difficult to enable on large existing projects that set up many floating 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 voids and/or 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 degredations after enabling type checked rules.

Resources