# @typescript-eslint/no-use-before-define

> Disallow using a variable, function, class, enum, or type above the line that declares it

Reading a `let`, `const`, or `class` before its declaration runs throws a `ReferenceError`. Reading a `var` early gives you `undefined` without any error. Function declarations do work before their line, but the reader needs to scroll down to find out what's being called.

A variable used in its own initializer, such as `const total = total + 1`, is reported too. Unlike ESLint's `no-use-before-define`, this rule also checks enums, type aliases, and interfaces.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-use-before-define" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-use-before-define" = ["error", {
  functions = true,
  variables = true,
  classes = true,
  enums = true,
  typedefs = true,
  ignoreTypeReferences = true,
  allowNamedExports = false,
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 3} */}
```ts
console.log(limit);
const limit = 10;

start(Mode.Fast);
function start(mode: Mode) {}

enum Mode {
  Fast,
  Slow,
}
```

Not reported:

{/* good */}
```ts
const limit = 10;
console.log(limit);

enum Mode {
  Fast,
  Slow,
}

function start(mode: Mode) {}
start(Mode.Fast);
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `functions` | `true` | Report function declarations that are used early. `false` allows every early use of them. |
| `variables` | `true` | With `false`, a function can mention a `var`, `let`, or `const` that's declared below it. An early use in the same scope is still reported. |
| `classes` | `true` | The same as `variables`, for classes. |
| `enums` | `true` | The same as `variables`, for enums. |
| `typedefs` | `true` | Report type aliases and interfaces that are used early. This only has an effect with `ignoreTypeReferences: false`. |
| `ignoreTypeReferences` | `true` | Allow early uses in a type position, such as `let user: User` or `typeof config`. |
| `allowNamedExports` | `false` | Allow `export { name }` above the declaration of `name`. |

The string `"nofunc"` is short for `{ "functions": false }`.

With `functions: false`, calling a function declaration early is allowed, because it's already defined when the file starts to run:

{/* good {"options": [{"functions": false}]} */}
```ts
start();

function start() {}
```

By default, only the position in the file counts, even in a function that runs later:

{/* bad */}
```ts
function isFull(count: number) {
  return count >= limit;
}

const limit = 10;
```

{/* good {"options": [{"variables": false}]} */}
```ts
function isFull(count: number) {
  return count >= limit;
}

const limit = 10;
```

An early use in the same scope runs before the declaration, so it's still reported:

{/* bad {"options": [{"variables": false}]} */}
```ts
console.log(limit);

const limit = 10;
```

Types don't exist when the code runs, so by default their order doesn't matter where they're used as types:

{/* good */}
```ts
let current: User;

type User = { name: string };
```

{/* bad {"options": [{"ignoreTypeReferences": false}]} */}
```ts
let current: User;

type User = { name: string };
```

{/* good {"options": [{"ignoreTypeReferences": false, "typedefs": false}]} */}
```ts
let current: User;

type User = { name: string };
```

With `allowNamedExports: true`, you can keep the export list at the top of the file:

{/* good {"options": [{"allowNamedExports": true}]} */}
```ts
export { limit };

const limit = 10;
```
