@typescript-eslint/no-use-before-define
Disallow using a variable, function, class, enum, or type above the line that declares it
Also called typescript-eslint/no-use-before-define, typescript/no-use-before-define
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:
[lint.rules]
"@typescript-eslint/no-use-before-define" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"@typescript-eslint/no-use-before-define" = ["error", {
functions = true,
variables = true,
classes = true,
enums = true,
typedefs = true,
ignoreTypeReferences = true,
allowNamedExports = false,
}]Examples#
console.log(limitlimit was used before it was defined.);
const limit = 10;
startstart was used before it was defined.(ModeMode was used before it was defined..Fast);
function start(mode: Mode) {}
enum Mode {
Fast,
Slow,
}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:
{ "functions": false }No problemsstart();
function start() {}By default, only the position in the file counts, even in a function that runs later:
function isFull(count: number) {
return count >= limitlimit was used before it was defined.;
}
const limit = 10;{ "variables": false }No problemsfunction 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:
{ "variables": false }1 problemconsole.log(limitlimit was used before it was defined.);
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 };{ "ignoreTypeReferences": false }1 problemlet current: UserUser was used before it was defined.;
type User = { name: string };{ "ignoreTypeReferences": false, "typedefs": false }No problemslet current: User;
type User = { name: string };With allowNamedExports: true, you can keep the export list at the top of the file:
{ "allowNamedExports": true }No problemsexport { limit };
const limit = 10;