Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

@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.

Configure

Off by default. To turn it on:

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

Every option, set to its default:

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,
}]

Examples

Reported:

console.log(limit);
const limit = 10;

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

enum Mode {
  Fast,
  Slow,
}

Not reported:

const limit = 10;
console.log(limit);

enum Mode {
  Fast,
  Slow,
}

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

Options

OptionDefaultWhat it does
functionstrueReport function declarations that are used early. false allows every early use of them.
variablestrueWith 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.
classestrueThe same as variables, for classes.
enumstrueThe same as variables, for enums.
typedefstrueReport type aliases and interfaces that are used early. This only has an effect with ignoreTypeReferences: false.
ignoreTypeReferencestrueAllow early uses in a type position, such as let user: User or typeof config.
allowNamedExportsfalseAllow 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:

start();

function start() {}

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

function isFull(count: number) {
  return count >= limit;
}

const limit = 10;
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:

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:

let current: User;

type User = { name: string };
let current: User;

type User = { name: string };
let current: User;

type User = { name: string };

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

export { limit };

const limit = 10;