---
description: 'Disallow accidentally using the "empty object" type.'
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-empty-object-type** for documentation.

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 `""`:

```ts
let anyNonNullishValue: {} = 'Intentionally allowed by TypeScript.';
```

Often, developers writing `{}` actually mean either:

- `object`: representing any _object_ value
- `unknown`: 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.

:::tip
If you do have a use case for an API allowing `{}`, you can always configure the [rule's options](#options), use an [ESLint disable comment](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1), or [disable the rule in your ESLint config](https://eslint.org/docs/latest/use/configure/rules#using-configuration-files-1).
:::

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.
- Interfaces that extend from multiple other interfaces.

## Examples

<Tabs>
<TabItem value="❌ Incorrect">

```ts
let anyObject: {};
let anyValue: {};

interface AnyObjectA {}
interface AnyValueA {}

type AnyObjectB = {};
type AnyValueB = {};
```

</TabItem>
<TabItem value="✅ Correct">

```ts
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 };
```

</TabItem>
</Tabs>

## Options

By default, this rule flags both interfaces and object types.

### `allowInterfaces`

Whether to allow empty interfaces, as one of:

- `'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 interface

Examples of code for this rule with `{ allowInterfaces: 'with-single-extends' }`:

<Tabs>
<TabItem value="❌ Incorrect">

```ts option='{ "allowInterfaces": "with-single-extends" }'
interface Foo {}
```

</TabItem>
<TabItem value="✅ Correct">

```ts option='{ "allowInterfaces": "with-single-extends" }'
interface Base {
  value: boolean;
}

interface Derived extends Base {}
```

</TabItem>
</Tabs>

### `allowObjectTypes`

Whether to allow empty object type literals, as one of:

- `'always'`: to always allow object type literals with no fields
- `'never'` _(default)_: to never allow object type literals with no fields

Examples of code for this rule with `{ allowObjectTypes: 'always' }`:

<Tabs>
<TabItem value="❌ Incorrect">

```ts option='{ "allowObjectTypes": "always" }'
interface Base {}
```

</TabItem>
<TabItem value="✅ Correct">

```ts option='{ "allowObjectTypes": "always" }'
type Base = {};
```

</TabItem>
</Tabs>

### `allowWithName`

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$' }`:

<Tabs>
<TabItem value="❌ Incorrect">

```ts option='{ "allowWithName": "Props$" }'
interface InterfaceValue {}

type TypeValue = {};
```

</TabItem>
<TabItem value="✅ Correct">

```ts option='{ "allowWithName": "Props$" }'
interface InterfaceProps {}

type TypeProps = {};
```

</TabItem>
</Tabs>

## When Not To Use It

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 Reading

- [Enhancement: [ban-types] Split the {} ban into a separate, better-phrased rule](https://github.com/typescript-eslint/typescript-eslint/issues/8700)
- [The Empty Object Type in TypeScript](https://www.totaltypescript.com/the-empty-object-type-in-typescript)
