# no-shadow

> Disallow a variable with the same name as one in an outer scope

When an inner variable has the same name as an outer one, you can't reach the outer one from there anymore. A reader who has the outer meaning in mind misreads the inner code, and moving a line in or out of the block silently changes what the name refers to.

{/* 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]
"no-shadow" = "error" # or "warn"
```

Every option, set to its default. The ones that are commented out are unset by default.

```toml bunfig.toml
[lint.rules]
"no-shadow" = ["error", {
  allow = [], # list of strings
  builtinGlobals = false,
  # "all", "functions", "never", "types" or "functions-and-types"
  # hoist = "functions",
  ignoreOnInitialization = false,
  ignoreTypeValueShadow = true,
  ignoreFunctionTypeParameterNameValueShadow = true,
}]
```

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

## Examples

Reported:

{/* bad */}
```js
const user = currentUser();

function greet(user) {
  return `Hello, ${user.name}`;
}
```

Not reported:

{/* good */}
```js
const user = currentUser();

function greet(guest) {
  return `Hello, ${guest.name}, I am ${user.name}`;
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `allow` | `[]` | Names that may be shadowed. |
| `builtinGlobals` | `false` | Also report names of globals, such as `Map` or `Object`. |
| `hoist` | `"functions"` | Whether to report when the outer declaration comes after the inner one. See below. |
| `ignoreOnInitialization` | `false` | Allow a callback's variable to shadow the variable that the call is assigned to. |
| `ignoreTypeValueShadow` | `true` | Allow a value with the same name as a type, and the reverse. |
| `ignoreFunctionTypeParameterNameValueShadow` | `true` | Allow the parameter names of function types and signatures. |

### `allow`

{/* good {"options": [{"allow": ["error"]}]} */}
```js
load((error, data) => {
  parse(data, (error, result) => {
    show(error ?? result);
  });
});
```

### `builtinGlobals`

{/* bad {"options": [{"builtinGlobals": true}]} */}
```js
function index(entries) {
  const Map = createIndex(entries);
  return Map;
}
```

### `hoist`

An inner variable can come before the outer declaration of the same name. `hoist` controls when that's reported.

| Value | What is reported |
| --- | --- |
| `"functions"` | Only when the outer declaration is a function declaration. |
| `"types"` | Only when it's a type alias or an interface. |
| `"functions-and-types"` | When it's any of these. |
| `"all"` | Always. |
| `"never"` | Never. |

{/* good */}
```js
function render() {
  const title = "Draft";
  return title;
}

const title = "Home";
```

{/* bad {"options": [{"hoist": "all"}]} */}
```js
function render() {
  const title = "Draft";
  return title;
}

const title = "Home";
```

### `ignoreOnInitialization`

{/* good {"options": [{"ignoreOnInitialization": true}]} */}
```js
const item = items.find((item) => item.selected);
```

### `ignoreTypeValueShadow`

{/* bad {"options": [{"ignoreTypeValueShadow": false}]} */}
```ts
type Config = { port: number };

function load() {
  const Config = read("config.json");
  return Config;
}
```

### `ignoreFunctionTypeParameterNameValueShadow`

{/* bad {"options": [{"ignoreFunctionTypeParameterNameValueShadow": false}]} */}
```ts
const value = 1;

type Handler = (value: string) => void;
```
