# @typescript-eslint/dot-notation

> Require `user.name` instead of `user["name"]`

`user["name"]` and `user.name` read the same property. The dot form is shorter and easier to read. Brackets are for keys that are computed or aren't valid names, such as `headers["content-type"]`.

This is `dot-notation` with types, which lets it make exceptions for private members, protected members, and index signatures.

With `bunfig.toml`, turning this rule on runs it in TypeScript files and `dot-notation` in JavaScript files, so nothing is reported twice. With an ESLint config, turn the other rule off when you use this one.

`--fix` rewrites the brackets to a dot.

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

## Configure

Off by default. This rule needs types, so turning it on makes `bun lint` type check your code first.

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/dot-notation" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/dot-notation" = ["error", {
  allowKeywords = true,
  allowPattern = "", # string
  allowPrivateClassPropertyAccess = false,
  allowProtectedClassPropertyAccess = false,
  allowIndexSignaturePropertyAccess = false,
}]
```

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

## Examples

Reported:

{/* bad */}
```ts
const user = { name: "Ada" };

console.log(user["name"]);
```

Not reported:

{/* good */}
```ts
const user = { name: "Ada", "last-login": 0 };
const key = "name" as const;

console.log(user.name, user[key], user["last-login"]);
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `allowKeywords` | `true` | `false` turns the rule around for reserved words: `obj.class` is reported, and `obj["class"]` is allowed. |
| `allowPattern` | `""` | A regular expression. Names that match it can be in brackets. |
| `allowPrivateClassPropertyAccess` | `false` | Allow brackets for `private` members. |
| `allowProtectedClassPropertyAccess` | `false` | Allow brackets for `protected` members. |
| `allowIndexSignaturePropertyAccess` | `false` | Allow brackets for keys that only an index signature declares. |

{/* bad {"options": [{"allowKeywords": false}], "count": 1} */}
```ts
const styles: Record<string, string> = {};

console.log(styles.class, styles["default"]);
```

{/* good {"options": [{"allowPattern": "^[a-z]+(_[a-z]+)+$"}]} */}
```ts
const row = { user_id: 1 };

console.log(row["user_id"]);
```

TypeScript doesn't check `private` and `protected` on bracket access, and tests sometimes use that to reach into a class:

{/* good {"options": [{"allowPrivateClassPropertyAccess": true}]} */}
```ts
class Counter {
  private count = 0;
}

console.log(new Counter()["count"]);
```

With `allowIndexSignaturePropertyAccess`, brackets can mark the keys that may not be there. `host` is declared, so it's still reported:

{/* bad {"options": [{"allowIndexSignaturePropertyAccess": true}], "count": 1} */}
```ts
interface Env {
  host: string;
  [name: string]: string;
}
declare const env: Env;

console.log(env["host"], env["PORT"]);
```

This option is always on when `noPropertyAccessFromIndexSignature` is set in your `tsconfig.json`, because TypeScript then rejects `env.PORT`:

{/* good {"compilerOptions": {"noPropertyAccessFromIndexSignature": true}} */}
```ts
declare const env: Record<string, string>;

console.log(env["PORT"]);
```
