β¬ οΈ Back to Table of Contents
π no-empty-object-type¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 2 |
| π¦ Imports | 3 |
| π Type Aliases | 4 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/no-empty-object-type.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'no-empty-object-type' |
meta.type |
'suggestion' |
meta.docs.description |
'Disallow accidentally using the "empty object" type' |
meta.docs.recommended |
'recommended' |
meta.hasSuggestions |
true |
meta.messages.noEmptyInterface |
noEmptyMessage('An empty interface declaration') |
meta.messages.noEmptyInterfaceWithSuper |
'An interface declaring no members is equivalent to its supertype.' |
meta.messages.noEmptyObject |
noEmptyMessage('The {} ("empty object") type') |
meta.messages.replaceEmptyInterface |
'Replace empty interface with {{replacement}}.' |
meta.messages.replaceEmptyInterfaceWithSuper |
'Replace empty interface with a type alias.' |
meta.messages.replaceEmptyObjectType |
'Replace {} with {{replacement}}.' |
meta.schema |
[ { type: 'object', additionalProperties: false, properties: { allowInterfaces: { type: 'string', description: 'Wheth... |
defaultOptions |
[ { allowInterfaces: 'never', allowObjectTypes: 'never', }, ] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESLint |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
Functions¶
create(context: any, [{ allowInterfaces, allowObjectβ¦: any): { TSTypeLiteral(node: any): void; TSInterfaceDeclaration(no⦶
Parameters:
contextany[{ allowInterfaces, allowObjectTypes, allowWithName }]any
Returns: { TSTypeLiteral(node: any): void; TSInterfaceDeclaration(node: any): void; }
Calls:
allowWithNameTester?.testcontext.sourceCode.getScopescope.set .get(node.id.name) ?.defs.somecontext.report['object', 'unknown'].mapcontext.sourceCode.getTextfixer.replaceTextallowWithNameTester.test
Code
create(context, [{ allowInterfaces, allowObjectTypes, allowWithName }]) {
const allowWithNameTester = allowWithName
? new RegExp(allowWithName, 'u')
: undefined;
return {
...(allowInterfaces !== 'always' && {
TSInterfaceDeclaration(node): void {
if (allowWithNameTester?.test(node.id.name)) {
return;
}
const extend = node.extends;
if (
node.body.body.length !== 0 ||
(extend.length === 1 &&
allowInterfaces === 'with-single-extends') ||
extend.length > 1
) {
return;
}
const scope = context.sourceCode.getScope(node);
const mergedWithOtherDeclaration = scope.set
.get(node.id.name)
?.defs.some(
def =>
def.node !== node &&
(def.node.type === AST_NODE_TYPES.ClassDeclaration ||
def.node.type === AST_NODE_TYPES.TSInterfaceDeclaration),
);
const isDefaultExport =
node.parent.type === AST_NODE_TYPES.ExportDefaultDeclaration;
const shouldSuggest = !mergedWithOtherDeclaration && !isDefaultExport;
if (extend.length === 0) {
context.report({
node: node.id,
messageId: 'noEmptyInterface',
data: { option: 'allowInterfaces' },
...(shouldSuggest && {
suggest: ['object', 'unknown'].map(replacement => ({
messageId: 'replaceEmptyInterface',
data: { replacement },
fix(fixer): TSESLint.RuleFix {
const id = context.sourceCode.getText(node.id);
const typeParam = node.typeParameters
? context.sourceCode.getText(node.typeParameters)
: '';
return fixer.replaceText(
node,
`type ${id}${typeParam} = ${replacement}`,
);
},
})),
}),
});
return;
}
context.report({
node: node.id,
messageId: 'noEmptyInterfaceWithSuper',
...(shouldSuggest && {
suggest: [
{
messageId: 'replaceEmptyInterfaceWithSuper',
fix(fixer): TSESLint.RuleFix {
const extended = context.sourceCode.getText(extend[0]);
const id = context.sourceCode.getText(node.id);
const typeParam = node.typeParameters
? context.sourceCode.getText(node.typeParameters)
: '';
return fixer.replaceText(
node,
`type ${id}${typeParam} = ${extended}`,
);
},
},
],
}),
});
},
}),
...(allowObjectTypes !== 'always' && {
TSTypeLiteral(node): void {
if (
node.members.length ||
node.parent.type === AST_NODE_TYPES.TSIntersectionType ||
(allowWithNameTester &&
node.parent.type === AST_NODE_TYPES.TSTypeAliasDeclaration &&
allowWithNameTester.test(node.parent.id.name))
) {
return;
}
context.report({
node,
messageId: 'noEmptyObject',
data: { option: 'allowObjectTypes' },
suggest: ['object', 'unknown'].map(replacement => ({
messageId: 'replaceEmptyObjectType',
data: { replacement },
fix: (fixer): TSESLint.RuleFix =>
fixer.replaceText(node, replacement),
})),
});
},
}),
};
}
noEmptyMessage(emptyType: string): string¶
Parameters:
emptyTypestring
Returns: string
Calls:
[${emptyType} allows any non-nullish value, including literals like `0` and `""`., "- If that's what you want, disable this lint rule with an inline comment or configure the '{{ option }}' rule option.", '- If you want a type meaning "any object", you probably wantobjectinstead.', '- If you want a type meaning "any value", you probably wantunknowninstead.', ].join
Code
(emptyType: string): string =>
[
`${emptyType} allows any non-nullish value, including literals like \`0\` and \`""\`.`,
"- If that's what you want, disable this lint rule with an inline comment or configure the '{{ option }}' rule option.",
'- If you want a type meaning "any object", you probably want `object` instead.',
'- If you want a type meaning "any value", you probably want `unknown` instead.',
].join('\n')
Type Aliases¶
AllowInterfaces¶
AllowObjectTypes¶
Options¶
type Options = [
{
allowInterfaces?: AllowInterfaces;
allowObjectTypes?: AllowObjectTypes;
allowWithName?: string;
},
];
MessageIds¶
type MessageIds = | 'noEmptyInterface'
| 'noEmptyInterfaceWithSuper'
| 'noEmptyObject'
| 'replaceEmptyInterface'
| 'replaceEmptyInterfaceWithSuper'
| 'replaceEmptyObjectType';
Generated by Syntax Scribe