Skip to content

Commit 6a7db49

Browse files
authored
feat: create new no-unnecessary-assertion rule (#1882)
* feat: create new `no-unnecessary-assertion` rule * feat: support "undefined" matchers too * test: add some more cases * docs: add doc for rule * fix: mark rule as requiring typechecking * fix: only import TypeScript at runtime if rule is enabled * test: disable automatic single run inference * fix: error if strict null checks is not enabled * test: ensure that we don't require typescript * perf: load typescript after we know strict null checks is enabled
1 parent 2d14097 commit 6a7db49

7 files changed

Lines changed: 617 additions & 5 deletions

File tree

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,10 @@ Manually fixable by
394394

395395
### Requires Type Checking
396396

397-
| Name           | Description | 💼 | ⚠️ | 🔧 | 💡 |
398-
| :--------------------------------------------- | :----------------------------------------------------------- | :-- | :-- | :-- | :-- |
399-
| [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | | | |
397+
| Name                     | Description | 💼 | ⚠️ | 🔧 | 💡 |
398+
| :----------------------------------------------------------------- | :----------------------------------------------------------- | :-- | :-- | :-- | :-- |
399+
| [no-unnecessary-assertion](docs/rules/no-unnecessary-assertion.md) | Disallow unnecessary assertions based on types | | | | |
400+
| [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | | | |
400401

401402
<!-- end auto-generated rules list -->
402403

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Disallow unnecessary assertions based on types (`no-unnecessary-assertion`)
2+
3+
💭 This rule requires
4+
[type information](https://typescript-eslint.io/linting/typed-linting).
5+
6+
<!-- end auto-generated rule header -->
7+
8+
When using TypeScript, runtime assertions based on types can often be omitted
9+
provided that the types are accurate.
10+
11+
## Rule details
12+
13+
This rule warns when you do an assertion about being `null` or `undefined` on
14+
something that cannot be those types, as that indicates either the assertion can
15+
be removed or the types need to be adjusted.
16+
17+
The following patterns are considered warnings:
18+
19+
```ts
20+
expect('hello world'.match('sunshine') ?? []).toBeNull();
21+
22+
expect(User.findOrThrow(1)).toBeDefined();
23+
24+
expect(map.getOrInsert('key', 'default')).not.toBeUndefined();
25+
```
26+
27+
The following patterns are not considered warnings:
28+
29+
```ts
30+
expect('hello world'.match('sunshine')).toBeNull();
31+
32+
expect(User.findOrNull(1)).toBeDefined();
33+
34+
expect(map.get('key')).not.toBeUndefined();
35+
```

src/__tests__/__snapshots__/rules.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ exports[`rules should export configs that refer to actual rules 1`] = `
3636
"jest/no-standalone-expect": "error",
3737
"jest/no-test-prefixes": "error",
3838
"jest/no-test-return-statement": "error",
39+
"jest/no-unnecessary-assertion": "error",
3940
"jest/no-unneeded-async-expect-function": "error",
4041
"jest/no-untyped-mock-factory": "error",
4142
"jest/padding-around-after-all-blocks": "error",
@@ -132,6 +133,7 @@ exports[`rules should export configs that refer to actual rules 1`] = `
132133
"jest/no-standalone-expect": "error",
133134
"jest/no-test-prefixes": "error",
134135
"jest/no-test-return-statement": "error",
136+
"jest/no-unnecessary-assertion": "error",
135137
"jest/no-unneeded-async-expect-function": "error",
136138
"jest/no-untyped-mock-factory": "error",
137139
"jest/padding-around-after-all-blocks": "error",

src/__tests__/rules.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
22
import { resolve } from 'path';
33
import plugin from '../';
44

5-
const numberOfRules = 67;
5+
const numberOfRules = 68;
66
const ruleNames = Object.keys(plugin.rules);
77
const deprecatedRules = Object.entries(plugin.rules)
88
.filter(([, rule]) => rule.meta.deprecated)

0 commit comments

Comments
 (0)