Skip to content

Commit

Permalink
feat(no-empty-interface): add allowSingleExtend option (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
timkraut authored and bradzacher committed Feb 14, 2019
1 parent 2a4aaaa commit bf46f8c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
17 changes: 17 additions & 0 deletions packages/eslint-plugin/docs/rules/no-empty-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,23 @@ interface Bar {
interface Baz extends Foo, Bar {}
```

### Options

This rule accepts a single object option with the following default configuration:

```json
{
"@typescript-eslint/no-empty-interface": [
"error",
{
"allowSingleExtends": false
}
]
}
```

- `allowSingleExtends: true` will silence warnings about extending a single interface without adding additional members

## When Not To Use It

If you don't care about having empty/meaningless interfaces, then you will not need this rule.
Expand Down
43 changes: 35 additions & 8 deletions packages/eslint-plugin/src/rules/no-empty-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
import { TSESTree } from '@typescript-eslint/typescript-estree';
import * as util from '../util';

export default util.createRule({
type Options = [
{
allowSingleExtends?: boolean;
}
];
type MessageIds = 'noEmpty' | 'noEmptyWithSuper';

export default util.createRule<Options, MessageIds>({
name: 'no-empty-interface',
meta: {
type: 'suggestion',
Expand All @@ -21,13 +28,28 @@ export default util.createRule({
noEmptyWithSuper:
'An interface declaring no members is equivalent to its supertype.'
},
schema: []
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowSingleExtends: {
type: 'boolean'
}
}
}
]
},
defaultOptions: [],
create(context) {
defaultOptions: [
{
allowSingleExtends: false
}
],
create(context, [{ allowSingleExtends }]) {
return {
TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration) {
if (node.body.body.length !== 0) {
// interface contains members --> Nothing to report
return;
}

Expand All @@ -37,10 +59,15 @@ export default util.createRule({
messageId: 'noEmpty'
});
} else if (node.extends.length === 1) {
context.report({
node: node.id,
messageId: 'noEmptyWithSuper'
});
// interface extends exactly 1 interface --> Report depending on rule setting
if (allowSingleExtends) {
return;
} else {
context.report({
node: node.id,
messageId: 'noEmptyWithSuper'
});
}
}
}
};
Expand Down
13 changes: 12 additions & 1 deletion packages/eslint-plugin/tests/rules/no-empty-interface.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ interface Bar {
// valid because extending multiple interfaces can be used instead of a union type
interface Baz extends Foo, Bar {}
`
`,
{
code: `
interface Foo {
name: string;
}
interface Bar extends Foo {}
`,
options: [{ allowSingleExtends: true }]
}
],
invalid: [
{
Expand Down Expand Up @@ -54,6 +64,7 @@ interface Foo {
interface Bar extends Foo {}
`,
options: [{ allowSingleExtends: false }],
errors: [
{
messageId: 'noEmptyWithSuper',
Expand Down

0 comments on commit bf46f8c

Please sign in to comment.