📄 no-empty-interface¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 2 |
| 📦 Imports | 5 |
| 📑 Type Aliases | 2 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin/src/rules/no-empty-interface.ts
📤 Default Export¶
| Property | Value |
|---|---|
name |
'no-empty-interface' |
meta.type |
'suggestion' |
meta.deprecated.deprecatedSince |
'8.0.0' |
meta.deprecated.replacedBy |
[ { rule: { name: '@typescript-eslint/no-empty-object-type', url: 'https://typescript-eslint.io/rules/no-empty-object... |
meta.deprecated.url |
'https://github.com/typescript-eslint/typescript-eslint/pull/8977' |
meta.docs.description |
'Disallow the declaration of empty interfaces' |
meta.fixable |
'code' |
meta.hasSuggestions |
true |
meta.messages.noEmpty |
'An empty interface is equivalent to {}.' |
meta.messages.noEmptyWithSuper |
'An interface declaring no members is equivalent to its supertype.' |
meta.replacedBy |
['@typescript-eslint/no-empty-object-type'] |
meta.schema |
[ { type: 'object', additionalProperties: false, properties: { allowSingleExtends: { type: 'boolean', description: 'W... |
defaultOptions |
[ { allowSingleExtends: false, }, ] |
Entry point: create — documented under Functions.
📦 Imports¶
| Name | Source |
|---|---|
TSESLint |
@typescript-eslint/utils |
ScopeType |
@typescript-eslint/scope-manager |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
isDefinitionFile |
../util |
Functions¶
create(context: any, [{ allowSingleExtends }]: any): { TSInterfaceDeclaration(node: any): void; }¶
Parameters:
contextany[{ allowSingleExtends }]any
Returns: { TSInterfaceDeclaration(node: any): void; }
Calls:
context.reportcontext.sourceCode.getTextfixer.replaceTextcontext.sourceCode.getScopescope.set .get(node.id.name) ?.defs.someisDefinitionFile (from ../util)
Internal Comments:
// interface contains members --> Nothing to report
// interface extends exactly 1 interface --> Report depending on rule setting
Code
create(context, [{ allowSingleExtends }]) {
return {
TSInterfaceDeclaration(node): void {
if (node.body.body.length !== 0) {
// interface contains members --> Nothing to report
return;
}
const extend = node.extends;
if (extend.length === 0) {
context.report({
node: node.id,
messageId: 'noEmpty',
});
} else if (
extend.length === 1 &&
// interface extends exactly 1 interface --> Report depending on rule setting
!allowSingleExtends
) {
const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix => {
let typeParam = '';
if (node.typeParameters) {
typeParam = context.sourceCode.getText(node.typeParameters);
}
return fixer.replaceText(
node,
`type ${context.sourceCode.getText(
node.id,
)}${typeParam} = ${context.sourceCode.getText(extend[0])}`,
);
};
const scope = context.sourceCode.getScope(node);
const mergedWithClassDeclaration = scope.set
.get(node.id.name)
?.defs.some(
def => def.node.type === AST_NODE_TYPES.ClassDeclaration,
);
const isInAmbientDeclaration =
isDefinitionFile(context.filename) &&
scope.type === ScopeType.tsModule &&
scope.block.declare;
const useAutoFix = !(
isInAmbientDeclaration || mergedWithClassDeclaration
);
context.report({
node: node.id,
messageId: 'noEmptyWithSuper',
...(useAutoFix
? { fix }
: !mergedWithClassDeclaration
? {
suggest: [
{
messageId: 'noEmptyWithSuper',
fix,
},
],
}
: null),
});
}
},
};
}
Internal helpers¶
Declared inside another function in this file.
fix(fixer: TSESLint.RuleFixer): TSESLint.RuleFix¶
Parameters:
fixerTSESLint.RuleFixer
Returns: TSESLint.RuleFix
Calls:
context.sourceCode.getTextfixer.replaceText
Code
(fixer: TSESLint.RuleFixer): TSESLint.RuleFix => {
let typeParam = '';
if (node.typeParameters) {
typeParam = context.sourceCode.getText(node.typeParameters);
}
return fixer.replaceText(
node,
`type ${context.sourceCode.getText(
node.id,
)}${typeParam} = ${context.sourceCode.getText(extend[0])}`,
);
}
Type Aliases¶
Options¶
MessageIds¶
Generated by Syntax Scribe