Linter · Rules
no-use-before-define
Disallow using a variable, function, or class above the line that declares it
Reading a let, const, or class before its declaration runs throws a ReferenceError. Reading a var early gives undefined without any error. Function declarations do work before their line, but a reader has to scroll down to find out what's being called.
The rule goes by position in the file. A function that mentions a variable declared below it is reported, even if the function only runs later. The options relax that.
Configure
Off by default. To turn it on:
[lint.rules]
"no-use-before-define" = "error" # or "warn"
Every option, set to its default:
[lint.rules]
"no-use-before-define" = ["error", {
functions = true,
classes = true,
variables = true,
allowNamedExports = false,
enums = true,
typedefs = true,
ignoreTypeReferences = true,
}]
Examples
Reported:
console.log(limit);
const limit = 10;
start();
function start() {}
const total = total + 1;
function report() {
return limit;
}
const limit = 10;
Not reported:
const limit = 10;
console.log(limit);
function start() {}
start();
Options
| Option | Default | What it does |
|---|---|---|
functions | true | Report function declarations that are used early. |
classes | true | With false, a function may mention a class that's declared below it. An early use in the same scope is still reported. |
variables | true | The same as classes, for var, let, and const. |
allowNamedExports | false | Allow export { name } above the declaration of name. |
enums | true | Report TypeScript enums that are used early. |
typedefs | true | Report type aliases and interfaces that are used early. |
ignoreTypeReferences | true | Allow early uses in a type position, such as let user: User or typeof config. |
The string "nofunc" is short for { "functions": false }.
With functions: false, you can call a function declaration early. It's already defined when the file starts to run:
start();
function start() {}
With variables: false, a function may mention a variable that's declared below it:
function report() {
return 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;
With allowNamedExports: true, you can keep the list of exports at the top of the file:
export { limit };
const limit = 10;
Types don't exist when the code runs, so by default you can name a type before it's declared:
let current: User;
interface User {
name: string;
}
With ignoreTypeReferences: false, the same code is reported:
let current: User;
interface User {
name: string;
}