diff --git a/packages/eslint-plugin/docs/rules/no-empty-interface.md b/packages/eslint-plugin/docs/rules/no-empty-interface.md index a300c81b1041..37aa7e4dbc11 100644 --- a/packages/eslint-plugin/docs/rules/no-empty-interface.md +++ b/packages/eslint-plugin/docs/rules/no-empty-interface.md @@ -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. diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 52e1d0ddf9ab..f4373a89375e 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -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({ name: 'no-empty-interface', meta: { type: 'suggestion', @@ -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; } @@ -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' + }); + } } } }; diff --git a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts index 2410509a1fcd..fb7b95009129 100644 --- a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts +++ b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts @@ -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: [ { @@ -54,6 +64,7 @@ interface Foo { interface Bar extends Foo {} `, + options: [{ allowSingleExtends: false }], errors: [ { messageId: 'noEmptyWithSuper', pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy