Skip to content

Commit a19af97

Browse files
committed
feat(ts-no-empty-object-type): new rule to prevent empty objects
1 parent ad97ccd commit a19af97

File tree

10 files changed

+229
-0
lines changed

10 files changed

+229
-0
lines changed

.README/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ Finally, enable all of the rules that you would like to use.
280280
"jsdoc/text-escaping": 1,
281281
"jsdoc/ts-prefer-function-type": 1,
282282
"jsdoc/ts-method-signature-style": 1,
283+
"jsdoc/ts-prefer-function-type": 1,
283284
"jsdoc/type-formatting": 1,
284285
"jsdoc/valid-types": 1 // Recommended
285286
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# `ts-no-empty-object-type`
2+
3+
Warns against use of the empty object type which, in TypeScript,
4+
means "any value that is defined".
5+
6+
## Options
7+
8+
{"gitdown": "options"}
9+
10+
|||
11+
|---|---|
12+
|Context|everywhere|
13+
|Tags|``|
14+
|Recommended|true|
15+
|Settings||
16+
|Options||
17+
18+
## Failing examples
19+
20+
<!-- assertions-failing tsNoEmptyObjectType -->
21+
22+
## Passing examples
23+
24+
<!-- assertions-passing tsNoEmptyObjectType -->

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ Finally, enable all of the rules that you would like to use.
307307
"jsdoc/text-escaping": 1,
308308
"jsdoc/ts-prefer-function-type": 1,
309309
"jsdoc/ts-method-signature-style": 1,
310+
"jsdoc/ts-prefer-function-type": 1,
310311
"jsdoc/type-formatting": 1,
311312
"jsdoc/valid-types": 1 // Recommended
312313
}
@@ -500,6 +501,7 @@ non-default-recommended fixer).
500501
|:heavy_check_mark:|:wrench:| [tag-lines](./docs/rules/tag-lines.md#readme) | Enforces lines (or no lines) before, after, or between tags. |
501502
||:wrench:| [text-escaping](./docs/rules/text-escaping.md#readme) | Auto-escape certain characters that are input within block and tag descriptions. |
502503
||:wrench:| [ts-method-signature-style](./docs/rules/ts-method-signature-style.md#readme) | Prefers either function properties or method signatures |
504+
|:heavy_check_mark:|| [ts-no-empty-object-type](./docs/rules/ts-no-empty-object-type.md#readme) | Warns against use of the empty object type |
503505
||:wrench:| [ts-prefer-function-type](./docs/rules/ts-prefer-function-type.md#readme) | Prefers function types over call signatures when there are no other properties. |
504506
||:wrench:| [type-formatting](./docs/rules/type-formatting.md#readme) | Formats JSDoc type values. |
505507
|:heavy_check_mark:|| [valid-types](./docs/rules/valid-types.md#readme) | Requires all types/namepaths to be valid JSDoc, Closure compiler, or TypeScript types (configurable in settings). |
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<a name="user-content-ts-no-empty-object-type"></a>
2+
<a name="ts-no-empty-object-type"></a>
3+
# <code>ts-no-empty-object-type</code>
4+
5+
Warns against use of the empty object type which, in TypeScript,
6+
means "any value that is defined".
7+
8+
<a name="user-content-ts-no-empty-object-type-options"></a>
9+
<a name="ts-no-empty-object-type-options"></a>
10+
## Options
11+
12+
13+
14+
|||
15+
|---|---|
16+
|Context|everywhere|
17+
|Tags|``|
18+
|Recommended|true|
19+
|Settings||
20+
|Options||
21+
22+
<a name="user-content-ts-no-empty-object-type-failing-examples"></a>
23+
<a name="ts-no-empty-object-type-failing-examples"></a>
24+
## Failing examples
25+
26+
The following patterns are considered problems:
27+
28+
````ts
29+
/**
30+
* @param {{}} someName
31+
*/
32+
// Message: No empty object type.
33+
34+
/**
35+
* @param {(string|{})} someName
36+
*/
37+
// Message: No empty object type.
38+
````
39+
40+
41+
42+
<a name="user-content-ts-no-empty-object-type-passing-examples"></a>
43+
<a name="ts-no-empty-object-type-passing-examples"></a>
44+
## Passing examples
45+
46+
The following patterns are not considered problems:
47+
48+
````ts
49+
/**
50+
* @param {{a: string}} someName
51+
*/
52+
53+
/**
54+
* @param {({a: string} & {b: number})} someName
55+
*/
56+
57+
/**
58+
* @param {BadType<} someName
59+
*/
60+
61+
/**
62+
* @param {{}} someName
63+
*/
64+
// Settings: {"jsdoc":{"mode":"jsdoc"}}
65+
````
66+

src/index-cjs.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import sortTags from './rules/sortTags.js';
6767
import tagLines from './rules/tagLines.js';
6868
import textEscaping from './rules/textEscaping.js';
6969
import tsMethodSignatureStyle from './rules/tsMethodSignatureStyle.js';
70+
import tsNoEmptyObjectType from './rules/tsNoEmptyObjectType.js';
7071
import tsPreferFunctionType from './rules/tsPreferFunctionType.js';
7172
import typeFormatting from './rules/typeFormatting.js';
7273
import validTypes from './rules/validTypes.js';
@@ -254,6 +255,7 @@ index.rules = {
254255
'tag-lines': tagLines,
255256
'text-escaping': textEscaping,
256257
'ts-method-signature-style': tsMethodSignatureStyle,
258+
'ts-no-empty-object-type': tsNoEmptyObjectType,
257259
'ts-prefer-function-type': tsPreferFunctionType,
258260
'type-formatting': typeFormatting,
259261
'valid-types': validTypes,
@@ -346,6 +348,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
346348
'jsdoc/tag-lines': warnOrError,
347349
'jsdoc/text-escaping': 'off',
348350
'jsdoc/ts-method-signature-style': 'off',
351+
'jsdoc/ts-no-empty-object-type': warnOrError,
349352
'jsdoc/ts-prefer-function-type': 'off',
350353
'jsdoc/type-formatting': 'off',
351354
'jsdoc/valid-types': warnOrError,

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import sortTags from './rules/sortTags.js';
7373
import tagLines from './rules/tagLines.js';
7474
import textEscaping from './rules/textEscaping.js';
7575
import tsMethodSignatureStyle from './rules/tsMethodSignatureStyle.js';
76+
import tsNoEmptyObjectType from './rules/tsNoEmptyObjectType.js';
7677
import tsPreferFunctionType from './rules/tsPreferFunctionType.js';
7778
import typeFormatting from './rules/typeFormatting.js';
7879
import validTypes from './rules/validTypes.js';
@@ -260,6 +261,7 @@ index.rules = {
260261
'tag-lines': tagLines,
261262
'text-escaping': textEscaping,
262263
'ts-method-signature-style': tsMethodSignatureStyle,
264+
'ts-no-empty-object-type': tsNoEmptyObjectType,
263265
'ts-prefer-function-type': tsPreferFunctionType,
264266
'type-formatting': typeFormatting,
265267
'valid-types': validTypes,
@@ -352,6 +354,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
352354
'jsdoc/tag-lines': warnOrError,
353355
'jsdoc/text-escaping': 'off',
354356
'jsdoc/ts-method-signature-style': 'off',
357+
'jsdoc/ts-no-empty-object-type': warnOrError,
355358
'jsdoc/ts-prefer-function-type': 'off',
356359
'jsdoc/type-formatting': 'off',
357360
'jsdoc/valid-types': warnOrError,

src/rules.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,6 +2952,9 @@ export interface Rules {
29522952
}
29532953
];
29542954

2955+
/** Warns against use of the empty object type */
2956+
"jsdoc/ts-no-empty-object-type": [];
2957+
29552958
/** Prefers function types over call signatures when there are no other properties. */
29562959
"jsdoc/ts-prefer-function-type":
29572960
| []

src/rules/tsNoEmptyObjectType.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import iterateJsdoc from '../iterateJsdoc.js';
2+
import {
3+
parse as parseType,
4+
traverse,
5+
} from '@es-joy/jsdoccomment';
6+
7+
export default iterateJsdoc(({
8+
settings,
9+
utils,
10+
}) => {
11+
if (settings.mode !== 'typescript') {
12+
return;
13+
}
14+
15+
/**
16+
* @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} tag
17+
*/
18+
const checkType = (tag) => {
19+
const potentialType = tag.type;
20+
let parsedType;
21+
try {
22+
parsedType = parseType(
23+
/** @type {string} */ (potentialType), 'typescript',
24+
);
25+
} catch {
26+
return;
27+
}
28+
29+
traverse(parsedType, (nde) => {
30+
switch (nde.type) {
31+
case 'JsdocTypeObject': {
32+
if (!nde.elements.length) {
33+
utils.reportJSDoc('No empty object type.', tag);
34+
}
35+
}
36+
}
37+
});
38+
};
39+
40+
const tags = utils.filterTags(({
41+
tag,
42+
}) => {
43+
return Boolean(tag !== 'import' && utils.tagMightHaveTypePosition(tag));
44+
});
45+
46+
for (const tag of tags) {
47+
if (tag.type) {
48+
checkType(tag);
49+
}
50+
}
51+
}, {
52+
iterateAllJsdocs: true,
53+
meta: {
54+
docs: {
55+
description: 'Warns against use of the empty object type',
56+
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/ts-no-empty-object-type.md#repos-sticky-header',
57+
},
58+
schema: [],
59+
type: 'suggestion',
60+
},
61+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
export default {
2+
invalid: [
3+
{
4+
code: `
5+
/**
6+
* @param {{}} someName
7+
*/
8+
`,
9+
errors: [
10+
{
11+
line: 3,
12+
message: 'No empty object type.',
13+
},
14+
],
15+
},
16+
{
17+
code: `
18+
/**
19+
* @param {(string|{})} someName
20+
*/
21+
`,
22+
errors: [
23+
{
24+
line: 3,
25+
message: 'No empty object type.',
26+
},
27+
],
28+
},
29+
],
30+
valid: [
31+
{
32+
code: `
33+
/**
34+
* @param {{a: string}} someName
35+
*/
36+
`,
37+
},
38+
{
39+
code: `
40+
/**
41+
* @param {({a: string} & {b: number})} someName
42+
*/
43+
`,
44+
},
45+
{
46+
code: `
47+
/**
48+
* @param {BadType<} someName
49+
*/
50+
`,
51+
},
52+
{
53+
code: `
54+
/**
55+
* @param {{}} someName
56+
*/
57+
`,
58+
settings: {
59+
jsdoc: {
60+
mode: 'jsdoc',
61+
},
62+
},
63+
},
64+
],
65+
};

test/rules/ruleNames.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"tag-lines",
6969
"text-escaping",
7070
"ts-method-signature-style",
71+
"ts-no-empty-object-type",
7172
"ts-prefer-function-type",
7273
"type-formatting",
7374
"valid-types"

0 commit comments

Comments
 (0)