# no-undef

> Disallow variables that are not declared anywhere

Using a name that no `import`, declaration, or parameter defines throws a `ReferenceError` when that line runs. It's usually a typo or a missing import, and you only find out when that code path runs.

Without a config file, `bun lint` knows the browser, service worker and Node.js globals, and `Bun`. In test files such as `math.test.js` it also knows `test`, `expect`, `describe` and the like.

This rule is on by default in JavaScript files. It's off in TypeScript files, where the type checker reports the same thing.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

On by default as an error. To turn it off:

```toml bunfig.toml
[lint.rules]
"no-undef" = "off" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"no-undef" = ["error", {
  typeof = false,
}]
```

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

## Examples

Reported:

{/* bad */}
```js
function total(items) {
  return items.reduce((sum, item) => sum + item.price, 0) * taxRate;
}
```

Not reported:

{/* good */}
```js
import { taxRate } from "./config.js";

function total(items) {
  return items.reduce((sum, item) => sum + item.price, 0) * taxRate;
}
```

In `math.test.js`:

{/* good {"filename": "math.test.js"} */}
```js
test("adds", () => {
  expect(1 + 1).toBe(2);
});
```

If a script tag or the host defines a global, declare it. For one file, use a comment:

{/* good */}
```js
/* global analytics */

analytics.track("signup");
```

An `eslint-env` comment from an older ESLint setup still works. It declares all the globals of an environment such as `jquery`, `mocha` or `webextensions`. With an ESLint config file it's an error, as in ESLint 9 and later.

{/* good */}
```js
/* eslint-env jquery */

$(".menu").hide();
```

For the whole project, use `bunfig.toml`:

```toml bunfig.toml
[lint.globals]
analytics = "readonly"
```

A name that the file tests with `typeof` isn't reported anywhere in that file. You've shown that you know it may be missing. With an ESLint config file only the `typeof` itself is allowed, as in ESLint.

{/* good */}
```js
if (typeof define === "function" && define.amd) {
  define(["jquery"], () => 1);
}
```

`bun lint --infer-globals` also accepts the globals that your project's types declare.

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `typeof` | `false` | Also report an undeclared name after `typeof`. |

`typeof` never throws, so `typeof name === "undefined"` is a safe way to test for a global that may be missing. That's why it's allowed by default:

{/* good */}
```js
if (typeof analytics !== "undefined") {
  console.log("analytics is loaded");
}
```

{/* bad {"options": [{"typeof": true}]} */}
```js
if (typeof analytics !== "undefined") {
  console.log("analytics is loaded");
}
```
