Skip to content

Commit

Permalink
feat(eslint-plugin): [no-unnesc-cond] check array predicates by default
Browse files Browse the repository at this point in the history
  • Loading branch information
Retsam committed Feb 7, 2020
1 parent 4c12dac commit 8f676df
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 48 deletions.
21 changes: 8 additions & 13 deletions packages/eslint-plugin/docs/rules/no-unnecessary-condition.md
Expand Up @@ -28,6 +28,12 @@ function bar<T>(arg: string) {
// arg can never be nullish, so ?. is unnecessary
return arg?.length;
}

// Checks array predicate return types, where possible
[
[1, 2],
[3, 4],
].filter(t => t); // number[] is always truthy
```

Examples of **correct** code for this rule:
Expand All @@ -50,6 +56,8 @@ function bar(arg?: string | null) {
// Necessary, since arg might be nullish
return arg?.length;
}

[0, 1, 2, 3].filter(t => t); // number can be truthy or falsy
```

## Options
Expand All @@ -74,19 +82,6 @@ for (; true; ) {}
do {} while (true);
```

- `checkArrayPredicates` (default: `false`) - if set checks that the return value from certain array method callbacks (`filter`, `find`, `some`, `every`) is necessarily conditional.

```ts
// Valid: numbers can be truthy or falsy.
[0, 1, 2, 3].filter(t => t);

// Invalid: arrays are always falsy.
[
[1, 2],
[3, 4],
].filter(t => t);
```

## When Not To Use It

The main downside to using this rule is the need for type information.
Expand Down
12 changes: 1 addition & 11 deletions packages/eslint-plugin/src/rules/no-unnecessary-condition.ts
Expand Up @@ -61,7 +61,6 @@ export type Options = [
{
allowConstantLoopConditions?: boolean;
ignoreRhs?: boolean;
checkArrayPredicates?: boolean;
},
];

Expand Down Expand Up @@ -96,9 +95,6 @@ export default createRule<Options, MessageId>({
ignoreRhs: {
type: 'boolean',
},
checkArrayPredicates: {
type: 'boolean',
},
},
additionalProperties: false,
},
Expand All @@ -125,13 +121,9 @@ export default createRule<Options, MessageId>({
{
allowConstantLoopConditions: false,
ignoreRhs: false,
checkArrayPredicates: false,
},
],
create(
context,
[{ allowConstantLoopConditions, checkArrayPredicates, ignoreRhs }],
) {
create(context, [{ allowConstantLoopConditions, ignoreRhs }]) {
const service = getParserServices(context);
const checker = service.program.getTypeChecker();
const sourceCode = context.getSourceCode();
Expand Down Expand Up @@ -299,8 +291,6 @@ export default createRule<Options, MessageId>({
function shouldCheckCallback(node: TSESTree.CallExpression): boolean {
const { callee } = node;
return (
// option is on
!!checkArrayPredicates &&
// looks like `something.filter` or `something.find`
callee.type === AST_NODE_TYPES.MemberExpression &&
callee.property.type === AST_NODE_TYPES.Identifier &&
Expand Down
Expand Up @@ -91,20 +91,7 @@ function test(a: string) {
/**
* Predicate functions
**/
// valid, with the flag off
`
[1,3,5].filter(() => true);
[1,2,3].find(() => false);
function truthy() {
return [];
}
function falsy() {}
[1,3,5].filter(truthy);
[1,2,3].find(falsy);
`,
{
options: [{ checkArrayPredicates: true }],
code: `
// with literal arrow function
[0,1,2].filter(x => x);
Expand All @@ -117,22 +104,16 @@ function length(x: string) {
// with non-literal array
function nonEmptyStrings(x: string[]) {
return x.filter(length);
}
`,
},
}`,
// Ignores non-array methods of the same name
{
options: [{ checkArrayPredicates: true }],
code: `
`
const notArray = {
filter: (func: () => boolean) => func(),
find: (func: () => boolean) => func(),
};
notArray.filter(() => true);
notArray.find(() => true);
`,
},

// Nullish coalescing operator
`
function test(a: string | null) {
Expand Down Expand Up @@ -336,7 +317,6 @@ function test(a: never) {

// Predicate functions
{
options: [{ checkArrayPredicates: true }],
code: `
[1,3,5].filter(() => true);
[1,2,3].find(() => { return false; });
Expand All @@ -363,7 +343,6 @@ function nothing3(x: [string, string]) {
],
},
{
options: [{ checkArrayPredicates: true }],
code: `
function truthy() {
return [];
Expand All @@ -380,7 +359,6 @@ function falsy() {}
// Supports generics
// TODO: fix this
// {
// options: [{ checkArrayPredicates: true }],
// code: `
// const isTruthy = <T>(t: T) => T;
// // Valid: numbers can be truthy or falsy (0).
Expand Down

0 comments on commit 8f676df

Please sign in to comment.