Skip to content

Commit

Permalink
feat: add rule no-unused-expressions (#272)
Browse files Browse the repository at this point in the history
This rule extends the ESLint's no-unused-expressions to ignore type cast
expressions.

ESLint's no-unused-expressions catches some likely mistakes, but it also
complains about bare type cast expressions. These are unlikely to be
mistakes and are useful in several situations.
  • Loading branch information
mkscrg authored and gajus committed Sep 25, 2017
1 parent f96ce98 commit de617ac
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions .README/README.md
Expand Up @@ -149,6 +149,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d
{"gitdown": "include", "file": "./rules/no-dupe-keys.md"}
{"gitdown": "include", "file": "./rules/no-primitive-constructor-types.md"}
{"gitdown": "include", "file": "./rules/no-types-missing-file-annotation.md"}
{"gitdown": "include", "file": "./rules/no-unused-expressions.md"}
{"gitdown": "include", "file": "./rules/no-weak-types.md"}
{"gitdown": "include", "file": "./rules/object-type-delimiter.md"}
{"gitdown": "include", "file": "./rules/require-parameter-type.md"}
Expand Down
34 changes: 34 additions & 0 deletions .README/rules/no-unused-expressions.md
@@ -0,0 +1,34 @@
### `no-unused-expressions`

An extension of [ESLint's `no-unused-expressions`](https://eslint.org/docs/rules/no-unused-expressions).
This rule ignores type cast expressions, but otherwise behaves the same as ESLint's
`no-unused-expressions`.

Bare type casts are useful, for example to assert the exhaustiveness of a `switch`:

```js
type Action
= { type: 'FOO', doFoo: (_: number) => void }
| { type: 'BAR', doBar: (_: string) => void };

type State = { foo: number, bar: string };

function runFooBar(action: Action, state: State): void {
switch (action.type) {
case 'FOO':
doFoo(state.foo);
break;
case 'BAR':
doBar(state.bar);
break;
default:
(action: empty); // type error when `Action` is extended with new types
console.error(`Impossible action: ${action.toString()}`);
}
}
```

This rule takes the same arguments as ESLint's `no-unused-expressions`. See
[that rule's documentation](https://eslint.org/docs/rules/no-unused-expressions) for details.

<!-- assertions noUnusedExpressions -->
2 changes: 2 additions & 0 deletions src/index.js
Expand Up @@ -7,6 +7,7 @@ import genericSpacing from './rules/genericSpacing';
import noDupeKeys from './rules/noDupeKeys';
import noPrimitiveConstructorTypes from './rules/noPrimitiveConstructorTypes';
import noTypesMissingFileAnnotation from './rules/noTypesMissingFileAnnotation';
import noUnusedExpressions from './rules/noUnusedExpressions';
import noWeakTypes from './rules/noWeakTypes';
import objectTypeDelimiter from './rules/objectTypeDelimiter';
import requireParameterType from './rules/requireParameterType';
Expand All @@ -32,6 +33,7 @@ const rules = {
'no-dupe-keys': noDupeKeys,
'no-primitive-constructor-types': noPrimitiveConstructorTypes,
'no-types-missing-file-annotation': noTypesMissingFileAnnotation,
'no-unused-expressions': noUnusedExpressions,
'no-weak-types': noWeakTypes,
'object-type-delimiter': objectTypeDelimiter,
'require-parameter-type': requireParameterType,
Expand Down
23 changes: 23 additions & 0 deletions src/rules/noUnusedExpressions.js
@@ -0,0 +1,23 @@
// A wrapper around ESLint's core rule no-unused-expressions, additionally ignores type cast
// expressions.

import coreNOE from 'eslint/lib/rules/no-unused-expressions';

const meta = coreNOE.meta;

const create = (context) => {
const coreChecks = coreNOE.create(context);

return {
ExpressionStatement (node) {
if (node.expression.type !== 'TypeCastExpression') {
coreChecks.ExpressionStatement(node);
}
}
};
};

export default {
create,
meta
};
15 changes: 15 additions & 0 deletions tests/rules/assertions/noUnusedExpressions.js
@@ -0,0 +1,15 @@
export default {
invalid: [
{
code: 'foo + 1',
errors: [{
message: 'Expected an assignment or function call and instead saw an expression.'
}]
}
],
valid: [
{
code: '(foo: number)'
}
]
};
1 change: 1 addition & 0 deletions tests/rules/index.js
Expand Up @@ -18,6 +18,7 @@ const reportingRules = [
'no-dupe-keys',
'no-primitive-constructor-types',
'no-types-missing-file-annotation',
'no-unused-expressions',
'no-weak-types',
'object-type-delimiter',
'require-parameter-type',
Expand Down

0 comments on commit de617ac

Please sign in to comment.