Disallow accidentally using the "empty object" type.
💡
Some problems reported by this rule are manually fixable by editor suggestions.
The {}
, or "empty object" type in TypeScript is a common source of confusion for developers unfamiliar with TypeScript's structural typing. {}
represents any non-nullish value, including literals like 0
and ""
:
let anyNonNullishValue: {} = 'Intentionally allowed by TypeScript.';
Often, developers writing {}
actually mean either:
object
: representing any object valueunknown
: representing any value at all, including null
and undefined
In other words, the "empty object" type {}
really means "any value that is defined". That includes arrays, class instances, functions, and primitives such as string
and symbol
.
To avoid confusion around the {}
type allowing any non-nullish value, this rule bans usage of the {}
type. That includes interfaces and object type aliases with no fields.
Note that this rule does not report on:
{}
as a type constituent in an intersection type (e.g. types like TypeScript's built-in type NonNullable<T> = T & {}
), as this can be useful in type system operations.eslint.config.mjs
export default tseslint.config({
rules: {
"@typescript-eslint/no-empty-object-type": "error"
}
});
.eslintrc.cjs
module.exports = {
"rules": {
"@typescript-eslint/no-empty-object-type": "error"
}
};
Try this rule in the playground ↗
Exampleslet anyObject: {};
let anyValue: {};
interface AnyObjectA {}
interface AnyValueA {}
type AnyObjectB = {};
type AnyValueB = {};
Open in Playground
let anyObject: object;
let anyValue: unknown;
type AnyObjectA = object;
type AnyValueA = unknown;
type AnyObjectB = object;
type AnyValueB = unknown;
let objectWith: { property: boolean };
interface InterfaceWith {
property: boolean;
}
type TypeWith = { property: boolean };
Open in Playground Options
This rule accepts the following options:
type Options = [
{
allowInterfaces?:
| 'never'
| 'with-single-extends'
| 'always';
allowObjectTypes?:
| 'never'
| 'always';
allowWithName?: string;
},
];
const defaultOptions: Options = [
{ allowInterfaces: 'never', allowObjectTypes: 'never' },
];
By default, this rule flags both interfaces and object types.
allowInterfaces
Whether to allow empty interfaces. Default: "never"
.
Allowed values are:
'always'
: to always allow interfaces with no fields'never'
(default): to never allow interfaces with no fields'with-single-extends'
: to allow empty interfaces that extend
from a single base interfaceExamples of correct code for this rule with { allowInterfaces: 'with-single-extends' }
:
allowObjectTypes
Whether to allow empty object type literals. Default: "never"
.
Allowed values are:
'always'
: to always allow object type literals with no fields'never'
(default): to never allow object type literals with no fieldsallowWithName
A stringified regular expression to allow interfaces and object type aliases with the configured name.
This can be useful if your existing code style includes a pattern of declaring empty types with {}
instead of object
.
Examples of code for this rule with { allowWithName: 'Props$' }
:
If your code commonly needs to represent the "any non-nullish value" type, this rule may not be for you. Projects that extensively use type operations such as conditional types and mapped types oftentimes benefit from disabling this rule.
Further ReadingRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4