@typescript-eslint/no-shadow
Disallow a declaration that hides one with the same name in an outer scope
Also called typescript-eslint/no-shadow, typescript/no-shadow
When an inner scope declares a name that an outer scope already has, you can't reach the outer one from there. A reader who saw the outer declaration first mistakes the inner uses for it, and a line moved from one scope to the other silently refers to a different variable.
It's the TypeScript version of no-shadow and takes the same options. Only the hoist default differs. It's "functions-and-types" here and "functions" there.
With bunfig.toml you can set either name. bun lint runs this rule in TypeScript files and no-shadow in JavaScript files, so nothing is reported twice. With an ESLint config, turn on only one of the two.
Configure#
Off by default. To turn it on:
[lint.rules]
"@typescript-eslint/no-shadow" = "error" # or "warn"Every option, set to its default. The ones that are commented out are unset by default.
[lint.rules]
"@typescript-eslint/no-shadow" = ["error", {
allow = [], # list of strings
builtinGlobals = false,
# "all", "functions", "functions-and-types", "never" or "types"
# hoist = "functions-and-types",
ignoreOnInitialization = false,
ignoreTypeValueShadow = true,
ignoreFunctionTypeParameterNameValueShadow = true,
}]Examples#
const timeout = 1000;
function retry(action: () => void) {
const timeouttimeout is already declared in the upper scope on line 1 column 7. = 50;
setTimeout(action, timeout);
}const timeout = 1000;
function retry(action: () => void) {
const delay = 50;
setTimeout(action, delay);
}A type parameter hides a type, and an enum member hides a variable inside the enum:
type Item = { id: number };
function first<ItemItem is already declared in the upper scope on line 1 column 6.>(items: Item[]) {
return items[0];
}
const Low = 10;
enum Priority {
LowLow is already declared in the upper scope on line 6 column 7.,
High = Low + 1,
}Options#
| Option | Default | What it does |
|---|---|---|
allow | [] | Names that may hide an outer declaration. |
builtinGlobals | false | Also report a name that hides a global, such as Array. |
hoist | "functions-and-types" | When to report a name that comes before the outer declaration it hides. See below. |
ignoreOnInitialization | false | Allow it in a callback that's part of the outer variable's initializer. |
ignoreTypeValueShadow | true | Allow a value to have the name of an outer type, and a type the name of an outer value. |
ignoreFunctionTypeParameterNameValueShadow | true | Allow a parameter in a function type or signature to have the name of an outer variable. |
builtinGlobals#
Reported with builtinGlobals: true:
{ "builtinGlobals": true }1 problemfunction first(Array: string[]Array is already a global variable.) {
return Array[0];
}hoist#
| Value | Outer declarations that count when they come after the inner name |
|---|---|
"all" | All. |
"functions" | Function declarations. |
"types" | Interfaces and type aliases. |
"functions-and-types" | All three. |
"never" | None. |
Here the outer port is a const that comes later, so this is allowed by default:
function listen() {
const port = 3000;
return port;
}
const port = 8080;It's reported with hoist: "all":
{ "hoist": "all" }1 problemfunction listen() {
const portport is already declared in the upper scope on line 6 column 7. = 3000;
return port;
}
const port = 8080;ignoreOnInitialization#
Not reported with ignoreOnInitialization: true:
{ "ignoreOnInitialization": true }No problemsdeclare const users: { active: boolean }[];
const user = users.find(user => user.active);ignoreTypeValueShadow#
A type and a value with the same name don't get in each other's way, so this is allowed by default:
type Config = { port: number };
function start() {
const Config = { port: 3000 };
return Config;
}ignoreFunctionTypeParameterNameValueShadow#
A function type's parameter is only a label. Set the option to false to report it:
{ "ignoreFunctionTypeParameterNameValueShadow": false }1 problemconst id = 1;
type Lookup = (id: numberid is already declared in the upper scope on line 1 column 7.) => string;