Skip to content

Commit

Permalink
feat(eslint-plugin): add new rule no-misused-promises (#612)
Browse files Browse the repository at this point in the history
* feat(eslint-plugin): add new rule no-misused-promises

* chore: review feedback

* chore: regenerate plugin configs
  • Loading branch information
princjef authored and bradzacher committed Jul 16, 2019
1 parent ceb2d32 commit 28a131d
Show file tree
Hide file tree
Showing 9 changed files with 662 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/eslint-plugin/README.md
Expand Up @@ -152,6 +152,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :heavy_check_mark: | :wrench: | |
| [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallows magic numbers | | | |
| [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :heavy_check_mark: | | |
| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | | | :thought_balloon: |
| [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :heavy_check_mark: | | |
| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :heavy_check_mark: | | |
| [`@typescript-eslint/no-object-literal-type-assertion`](./docs/rules/no-object-literal-type-assertion.md) | Forbids an object literal to appear in a type assertion expression | :heavy_check_mark: | | |
Expand Down
119 changes: 119 additions & 0 deletions packages/eslint-plugin/docs/rules/no-misused-promises.md
@@ -0,0 +1,119 @@
# Avoid using promises in places not designed to handle them (no-misused-promises)

This rule forbids using promises 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.

## Rule Details

Examples of **incorrect** code for this rule with `checksConditionals: true`:

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

if (promise) {
// Do something
}

const val = promise ? 123 : 456;

while (promise) {
// Do something
}
```

Examples of **incorrect** code for this rule with `checksVoidReturn: true`:

```ts
[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 () => {
await doSomething();
});
```

Examples of **correct** code for this rule:

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

if (await promise) {
// Do something
}

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

while (await promise) {
// Do something
}

for (const value of [1, 2, 3]) {
await doSomething(value);
}

new Promise((resolve, reject) => {
// Do something
resolve();
});

const eventEmitter = new EventEmitter();
eventEmitter.on('some-event', () => {
doSomething();
});
```

## Options

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

If you don't want functions that return promises where a void return is
expected to be checked, your configuration will look like this:

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

Likewise, if you don't want to check conditionals, you can configure the rule
like this:

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

## 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.

## Related to

- [`no-floating-promises`]('./no-floating-promises.md')

## Further Reading

- [Typescript void function assignability](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning-void)
1 change: 1 addition & 0 deletions packages/eslint-plugin/src/configs/all.json
Expand Up @@ -36,6 +36,7 @@
"no-magic-numbers": "off",
"@typescript-eslint/no-magic-numbers": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-object-literal-type-assertion": "error",
Expand Down
4 changes: 3 additions & 1 deletion packages/eslint-plugin/src/configs/base.json
Expand Up @@ -3,5 +3,7 @@
"parserOptions": {
"sourceType": "module"
},
"plugins": ["@typescript-eslint"]
"plugins": [
"@typescript-eslint"
]
}
2 changes: 0 additions & 2 deletions packages/eslint-plugin/src/configs/recommended.json
Expand Up @@ -24,13 +24,11 @@
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-object-literal-type-assertion": "error",
"@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/no-triple-slash-reference": "error",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "warn",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/type-annotation-spacing": "error"
}
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin/src/rules/index.ts
Expand Up @@ -27,6 +27,7 @@ import noForInArray from './no-for-in-array';
import noInferrableTypes from './no-inferrable-types';
import noMagicNumbers from './no-magic-numbers';
import noMisusedNew from './no-misused-new';
import noMisusedPromises from './no-misused-promises';
import noNamespace from './no-namespace';
import noNonNullAssertion from './no-non-null-assertion';
import noObjectLiteralTypeAssertion from './no-object-literal-type-assertion';
Expand Down Expand Up @@ -89,6 +90,7 @@ export default {
'no-inferrable-types': noInferrableTypes,
'no-magic-numbers': noMagicNumbers,
'no-misused-new': noMisusedNew,
'no-misused-promises': noMisusedPromises,
'no-namespace': noNamespace,
'no-non-null-assertion': noNonNullAssertion,
'no-object-literal-type-assertion': noObjectLiteralTypeAssertion,
Expand Down

0 comments on commit 28a131d

Please sign in to comment.