# no-inner-declarations

> Disallow `function` and, optionally, `var` declarations in nested blocks

Outside strict mode, a function declared inside an `if` or a loop is also visible after the block, but it only has a value once the block has run. Whether a call works depends on which branch was taken.

In strict mode the function belongs to its block, like a `let`, so by default it isn't reported there. Modules and class bodies are always strict. That leaves CommonJS files and scripts without `"use strict"`.

{/* 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-inner-declarations" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"no-inner-declarations" = [
  "error",
  "functions", # "functions" or "both"
  {
    blockScopedFunctions = "allow", # "allow" or "disallow"
  },
]
```

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

## Examples

Reported:

{/* bad {"filename": "logger.cjs"} */}
```js
if (process.env.DEBUG) {
  function log(message) {
    console.log(message);
  }
}

log("ready"); // TypeError unless DEBUG is set
```

Not reported:

{/* good {"filename": "logger.cjs"} */}
```js
function log(message) {
  if (process.env.DEBUG) {
    console.log(message);
  }
}

log("ready");
```

Not reported either, because the file is in strict mode and `log` stays in its block:

{/* good {"filename": "logger.cjs"} */}
```js
"use strict";

if (process.env.DEBUG) {
  function log(message) {
    console.log(message);
  }
  log("ready");
}
```

## Options

```toml bunfig.toml
[lint.rules]
no-inner-declarations = ["error", "both", { blockScopedFunctions = "disallow" }]
```

The first option says what to look at:

| Option | What it does |
| --- | --- |
| `"functions"` (default) | Report `function` declarations in nested blocks. |
| `"both"` | Also report `var` declarations in nested blocks. |

A `var` belongs to the whole function, no matter which block it's written in:

{/* bad {"options": ["both"]} */}
```js
if (user.isAdmin) {
  var role = "admin";
}
```

{/* good {"options": ["both"]} */}
```js
let role;
if (user.isAdmin) {
  role = "admin";
}
```

The second option is an object:

| Option | Default | What it does |
| --- | --- | --- |
| `blockScopedFunctions` | `"allow"` | With `"disallow"`, report functions in nested blocks in strict mode too. |
| `namespaces` | `"disallow"` | Only for an oxlint config, where the rule also reports declarations directly inside a TypeScript `namespace`. `"allow"` turns that off. `bunfig.toml` rejects this option. |

{/* bad {"options": ["functions", {"blockScopedFunctions": "disallow"}]} */}
```js
if (process.env.DEBUG) {
  function log(message) {
    console.log(message);
  }
  log("ready");
}
```
