Skip to content

Commit 551360f

Browse files
authored
Merge pull request #55 from buildo/pure-statement
Add no-discarded-pure-expression
2 parents 13a9992 + 597b90f commit 551360f

20 files changed

+894
-25
lines changed

README.md

+60-14
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,48 @@ and enable the rules you want, for example
3838
}
3939
```
4040

41+
If you want to enable rules that require type information (see the table below),
42+
then you will also need to add some extra info:
43+
44+
```js
45+
module.exports = {
46+
plugins: ["fp-ts"],
47+
parserOptions: {
48+
tsconfigRootDir: __dirname,
49+
project: ["./tsconfig.json"],
50+
},
51+
rules: {
52+
"fp-ts/no-discarded-pure-expression": "error",
53+
},
54+
};
55+
```
56+
57+
If your project is a multi-package monorepo, you can follow the instructions
58+
[here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/MONOREPO.md).
59+
60+
> ⚠️ Note that you will need to make the ESLint config file a .js file, due to
61+
> the need of setting `tsconfigRootDir` to `__dirname`. This is necessary to
62+
> make both editor integrations and the CLI work with the correct path. More
63+
> info here: https://github.com/typescript-eslint/typescript-eslint/issues/251
64+
4165
## List of supported rules
4266

43-
- [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md): Disallow imports from
44-
'fp-ts/lib' (autofixable 🔧)
45-
- [fp-ts/no-pipeable](docs/rules/no-pipeable.md): Disallow imports from the
46-
'pipeable' module (autofixable 🔧)
47-
- [fp-ts/no-module-imports](docs/rules/no-module-imports.md): Disallow imports
48-
from fp-ts modules (autofixable 🔧)
49-
- [fp-ts/no-redundant-flow](docs/rules/no-redundant-flow.md): Remove redundant
50-
uses of flow (autofixable 🔧)
51-
- [fp-ts/prefer-traverse](docs/rules/prefer-traverse.md): Replace map + sequence
52-
with traverse (autofixable 🔧)
53-
- [fp-ts/prefer-chain](docs/rules/prefer-chain.md): Replace map + flatten with
54-
chain (autofixable 🔧)
55-
- [fp-ts/prefer-bimap](docs/rules/prefer-bimap.md): Replace map + mapLeft with
56-
bimap (autofixable 🔧)
67+
| Rule | Description | Fixable | Requires type-checking |
68+
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | :-----: | :--------------------: |
69+
| [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md) | Disallow imports from `fp-ts/lib/` | 🔧 | |
70+
| [fp-ts/no-pipeable](docs/rules/no-pipeable.md) | Disallow imports from the `pipeable` module | 🔧 | |
71+
| [fp-ts/no-module-imports](docs/rules/no-module-imports.md) | Disallow imports from fp-ts modules | 🔧 | |
72+
| [fp-ts/no-redundant-flow](docs/rules/no-redundant-flow.md) | Remove redundant uses of `flow` | 🔧 | |
73+
| [fp-ts/prefer-traverse](docs/rules/prefer-traverse.md) | Replace `map` + `sequence` with `traverse` | 💡 | |
74+
| [fp-ts/prefer-chain](docs/rules/prefer-chain.md) | Replace `map` + `flatten` with `chain` | 💡 | |
75+
| [fp-ts/prefer-bimap](docs/rules/prefer-bimap.md) | Replace `map` + `mapLeft` with `bimap` | 💡 | |
76+
| [fp-ts/no-discarded-pure-expression](docs/rules/no-discarded-pure-expression.md) | Disallow expressions returning pure data types (like `Task` or `IO`) in statement position | 💡 | 🦄 |
77+
78+
### Fixable legend:
79+
80+
🔧 = auto-fixable via `--fix` (or via the appropriate editor configuration)
81+
82+
💡 = provides in-editor suggestions that need to be applied manually
5783

5884
## Configurations
5985

@@ -74,6 +100,26 @@ The rules included in this configuration are:
74100
- [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md)
75101
- [fp-ts/no-pipeable](docs/rules/no-pipeable.md)
76102

103+
### Recommended requiring type-checking
104+
105+
We also provide a `recommended-requiring-type-checking` which includes
106+
recommended rules which require type information.
107+
108+
This configuration needs to be included _in addition_ to the `recommended` one:
109+
110+
```
111+
{
112+
"extends": [
113+
"plugin:fp-ts/recommended"
114+
"plugin:fp-ts/recommended-requiring-type-checking"
115+
]
116+
}
117+
```
118+
119+
> 👉 You can read more about linting with type information, including
120+
> performance condideration
121+
> [here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md)
122+
77123
### All
78124

79125
The plugin also defines an `all` configuration which includes every available
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Disallow expressions returning pure data types (like `Task` or `IO`) where `void` or `unknown` is expected or in statement position (fp-ts/no-discarded-pure-expression)
2+
3+
Expressions which return a pure data type, such as `IO`, `Task` and their
4+
variants, should normally be passed as an argument, returned, or run.
5+
6+
Failing to do so causes the program represented by `IO` or `Task` to never be
7+
run, leading to surprising behavior which is normally difficult to debug.
8+
9+
This rule covers two common scenarios that are common programming errors:
10+
11+
- returning pure data types where `void` or `unknown` is expected (for instance,
12+
in event handlers) without running them
13+
14+
- writing expressions that return pure data types in statement position (without
15+
returning them or running them)
16+
17+
**💡 Fixable**: This rule provides in-editor suggested fixes.
18+
19+
## Rule Details
20+
21+
Examples of **incorrect** code for this rule:
22+
23+
```ts
24+
import { task } from "fp-ts";
25+
26+
declare const myCommand: (n: number) => Task<string>;
27+
28+
function woops() {
29+
myCommand(1); // the task will never run, since is not being run nor returned
30+
}
31+
```
32+
33+
```ts
34+
declare const MyComponent: (props: { handler: () => void }) => JSX.Element;
35+
36+
declare const myCommand: (n: number) => Task<string>;
37+
38+
export function Foo() {
39+
return (
40+
<MyComponent
41+
handler={() => myCommand(1)} // bug, the Task will never execute
42+
/>;
43+
)
44+
}
45+
```
46+
47+
```ts
48+
import { task } from "fp-ts";
49+
50+
declare function foo(arg1: number, callbackUnknown: () => unknown): void;
51+
52+
declare const myCommand: (n: number) => Task<string>;
53+
54+
foo(
55+
2,
56+
() => myCommand(1) // bug, the Task will never execute
57+
);
58+
```
59+
60+
Examples of **correct** code for this rule:
61+
62+
```ts
63+
import { task } from "fp-ts";
64+
65+
declare const myCommand: (n: number) => Task<string>;
66+
67+
function ok() {
68+
return myCommand(1);
69+
}
70+
```
71+
72+
```ts
73+
declare const MyComponent: (props: { handler: () => void }) => JSX.Element;
74+
75+
declare const myCommand: (n: number) => Task<string>;
76+
77+
export function Foo() {
78+
return (
79+
<MyComponent
80+
handler={() => myCommand(1)()}
81+
/>;
82+
)
83+
}
84+
```
85+
86+
```ts
87+
import { task } from "fp-ts";
88+
89+
declare function foo(arg1: number, callbackUnknown: () => unknown): void;
90+
91+
declare const myCommand: (n: number) => Task<string>;
92+
93+
foo(2, () => myCommand(1)());
94+
```

docs/rules/no-lib-imports.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ without the `lib` prefix, which improves ergonomics and tree-shakeability.
66
> Note: this change was introduced in fp-ts 2.8.0. If you are using an older
77
> version, do not enable this rule
88
9-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
9+
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
1010
command line.
1111

1212
## Rule Details

docs/rules/no-module-imports.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Disallow imports from fp-ts modules, such as `fp-ts/Option`.
55
The `function` module is an exception and it's allowed nonetheless, since it's
66
not exported from fp-ts's index.
77

8-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
8+
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
99
command line.
1010

1111
## Rule Details

docs/rules/no-pipeable.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Disallow imports from the `pipeable` module. `pipeable` has been deprecated and
44
it will be removed in future versions of fp-ts. It's recommended to import
55
`pipe` from the `function` module instead.
66

7-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
7+
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
88
command line.
99

1010
> Note: the autofix is available only when importing `pipe`

docs/rules/no-redundant-flow.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
Suggest removing `flow` when it only has one argument. This can happen after a
44
refactoring that removed some combinators from a flow expression.
55

6-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
7-
command line.
6+
**💡 Fixable**: This rule provides in-editor suggested fixes.
87

98
## Rule Details
109

docs/rules/prefer-bimap.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
Suggest replacing the combination of `map` followed by `mapLeft` (or vice-versa)
44
with `bimap`.
55

6-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
7-
command line.
6+
**💡 Fixable**: This rule provides in-editor suggested fixes.
87

98
## Rule Details
109

docs/rules/prefer-chain.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
Suggest replacing the combination of `map` (or `mapWithIndex`) followed by
44
`flatten` with `chain` (or `chainWithIndex`).
55

6-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
7-
command line.
6+
**💡 Fixable**: This rule provides in-editor suggested fixes.
87

98
## Rule Details
109

docs/rules/prefer-traverse.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
Suggest replacing the combination of `map` (or `mapWithIndex`) followed by
44
`sequence` with `traverse` (or `traverseWithIndex`).
55

6-
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
7-
command line.
6+
**💡 Fixable**: This rule provides in-editor suggested fixes.
87

98
## Rule Details
109

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"scripts": {
1818
"preversion": "yarn lint && yarn test && yarn build",
1919
"build": "rimraf lib && yarn tsc",
20+
"pretest": "yarn --cwd tests/fixtures/fp-ts-project install",
2021
"test": "jest",
2122
"lint": "eslint src/**/*.ts"
2223
},

src/index.ts

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ const potentialErrors = {
55
"no-lib-imports": require("./rules/no-lib-imports").default,
66
"no-pipeable": require("./rules/no-pipeable").default,
77
"no-module-imports": require("./rules/no-module-imports").default,
8+
"no-discarded-pure-expression": require("./rules/no-discarded-pure-expression")
9+
.default,
810
};
911

1012
const suggestions = {
@@ -27,6 +29,12 @@ export const configs = {
2729
"fp-ts/no-pipeable": "error",
2830
},
2931
},
32+
"recommended-requiring-type-checking": {
33+
plugins: ["fp-ts"],
34+
rules: {
35+
"fp-ts/no-discarded-pure-expression": "error",
36+
},
37+
},
3038
all: {
3139
plugins: ["fp-ts"],
3240
rules: {

0 commit comments

Comments
 (0)