Back to Biomejs

noMisusedPromises

src/content/docs/linter/rules/no-misused-promises.mdx

latest16.2 KB
Original Source

import { Tabs, TabItem } from '@astrojs/starlight/components';

<Tabs> <TabItem label="TypeScript and TSX" icon="seti:typescript"> :::caution This rule is part of the [nursery](/linter/#nursery) group. This means that it is experimental and the behavior can change at any time. ::: :::note This rule belongs to the types domain. This means that its activation will activate the Biome Scanner to scan the files of your project, and enable the type inference engine. Read more about it in the [documentation page](/linter/domains#types) ::: ## Summary - Rule available since: `v2.1.0` - Diagnostic Category: [`lint/nursery/noMisusedPromises`](/reference/diagnostics#diagnostic-category) - This rule has an [**unsafe**](/linter/#unsafe-fixes) fix. - The default severity of this rule is [**information**](/reference/diagnostics#information). - This rule belongs to the following domains: - [`types`](/linter/domains#types) - Sources: - Same as [`@typescript-eslint/no-misused-promises`](https://typescript-eslint.io/rules/no-misused-promises)

How to configure

json
{
	"linter": {
		"rules": {
			"nursery": {
				"noMisusedPromises": "error"
			}
		}
	}
}

Description

Disallow Promises to be used in places where they are almost certainly a mistake.

In most cases, if you assign a Promise somewhere a Promise is not allowed, the TypeScript compiler will be able to catch such a mistake. But there are a few places where TypeScript allows them -- they're not necessarily a mistake -- even though they could be considered almost certainly to be one.

This rule disallows using Promises in such places.

Examples

Invalid

js
const promise = Promise.resolve('value');
if (promise) { /* This branch will always execute */ }
<pre class="language-text"><code class="language-text"><a href="file:///promise-in-condition.js">/promise-in-condition.js</a>:2:5 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise was found where a conditional was expected.</span> <strong>1 │ </strong>const promise = Promise.resolve('value'); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong>if (promise) &#123; /&#42; This branch will always execute &#42;/ &#125; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise is always truthy, so this is most likely a mistake.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">You may have intended to &#96;await&#96; the Promise instead.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>
js
const promise = Promise.resolve('value');
const val = promise ? 123 : 456; // Always evaluates to `123`.
<pre class="language-text"><code class="language-text"><a href="file:///promise-in-ternary-condition.js">/promise-in-ternary-condition.js</a>:2:13 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise was found where a conditional was expected.</span> <strong>1 │ </strong>const promise = Promise.resolve('value'); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong>const val = promise ? 123 : 456; // Always evaluates to &#96;123&#96;. <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise is always truthy, so this is most likely a mistake.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">You may have intended to &#96;await&#96; the Promise instead.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>
js
// The following filter has no effect:
const promise = Promise.resolve('value');
[1, 2, 3].filter(() => promise);
<pre class="language-text"><code class="language-text"><a href="file:///promise-in-filter.js">/promise-in-filter.js</a>:3:18 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This function returns a Promise where a conditional was expected.</span> <strong>1 │ </strong>// The following filter has no effect: <strong>2 │ </strong>const promise = Promise.resolve('value'); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong>[1, 2, 3].filter(() =&gt; promise); <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>4 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise is always truthy, so this is most likely a mistake.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">You may have intended to &#96;await&#96; the Promise, but this does not work inside a synchronous callback.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>
js
const promise = Promise.resolve('value');
while (promise) { /* This is an endless loop */ }
<pre class="language-text"><code class="language-text"><a href="file:///promise-while-condition.js">/promise-while-condition.js</a>:2:8 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise was found where a conditional was expected.</span> <strong>1 │ </strong>const promise = Promise.resolve('value'); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong>while (promise) &#123; /&#42; This is an endless loop &#42;/ &#125; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise is always truthy, so this is most likely a mistake.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">You may have intended to &#96;await&#96; the Promise instead.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>
js
// Using a `Promise` as an iterable expands to nothing:
const getData = () => fetch('/');
console.log({ foo: 42, ...getData() });
<pre class="language-text"><code class="language-text"><a href="file:///spread-promise.js">/spread-promise.js</a>:3:27 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">A Promise was found where an iterable was expected.</span> <strong>1 │ </strong>// Using a &#96;Promise&#96; as an iterable expands to nothing: <strong>2 │ </strong>const getData = () =&gt; fetch('/'); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong>console.log(&#123; foo: 42, ...getData() &#125;); <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>4 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">The spread syntax is used to expand an iterable, but a Promise needs to be &#96;await&#96;-ed to take its value.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>
js
// These `fetch`-es are not `await`-ed in order:
[1, 2, 3].forEach(async value => {
    await fetch(`/${value}`);
});
<pre class="language-text"><code class="language-text"><a href="file:///promise-in-forEach.js">/promise-in-forEach.js</a>:2:19 <a href="https://biomejs.dev/linter/rules/no-misused-promises">lint/nursery/noMisusedPromises</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This function returns a Promise, but no return value was expected.</span> <strong>1 │ </strong>// These &#96;fetch&#96;-es are not &#96;await&#96;-ed in order: <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong>[1, 2, 3].forEach(async value =&gt; &#123; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong> await fetch(&#96;/$&#123;value&#125;&#96;); <strong><span style="color: Tomato;">&gt;</span></strong> <strong>4 │ </strong>&#125;); <strong> │ </strong><strong><span style="color: Tomato;">^</span></strong> <strong>5 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This may not have the desired result if you expect the Promise to be &#96;await&#96;-ed.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit </span><span style="color: lightgreen;"><a href="https://biomejs.dev/linter/#nursery">https://biomejs.dev/linter/#nursery</a></span><span style="color: lightgreen;"> for more information.</span> </code></pre>

Valid

js
const promise = Promise.resolve('value');
if (await promise) { /* Do something */ }

const val = (await promise) ? 123 : 456;

while (await promise) { /* Do something */ }

const getData = () => fetch('/');
console.log({ foo: 42, ...(await getData()) });

// for-of puts `await` in outer context:
for (const value of [1, 2, 3]) {
    await doSomething(value);
}
</TabItem> </Tabs>