# import/no-duplicates

> Disallow importing the same module more than once in a file

Two `import` lines for one module make it harder to see what a file takes from it, and they're often left over from a merge. One line says it all.

The rule compares the files that the paths resolve to, so `./utils` and `./utils.js` count as the same module. Each of the imports is reported.

A namespace import (`import * as`) can't be merged with named imports, so it's allowed next to one. The same goes for `import type` next to a value import.

`--fix` merges the imports into the first one.

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

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"import/no-duplicates" = ["error", {
  prefer-inline = false,
  considerQueryString = false,
}]
```

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

## Examples

Reported:

{/* bad {"count": 2} */}
```js
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { writeFile } from "node:fs/promises";
```

{/* file "utils.js" */}
```js utils.js
export const clamp = (n, min, max) => Math.min(Math.max(n, min), max);
export const sum = items => items.reduce((a, b) => a + b, 0);
```

{/* bad {"count": 2} */}
```js
import { clamp } from "./utils";
import { sum } from "./utils.js";
```

Not reported:

{/* good */}
```js
import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
```

{/* good */}
```ts
import * as React from "react";
import { useState } from "react";
import type { ReactNode } from "react";
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `prefer-inline` | `false` | Report `import type { A }` next to `import { b }` from the same module. `--fix` merges them as `import { type A, b }`. |
| `considerQueryString` | `false` | Resolve the part of a path before a `?` and compare the part after it as text. |

{/* bad {"options": [{"prefer-inline": true}]} */}
```ts
import { useState } from "react";
import type { ReactNode } from "react";
```

{/* good {"options": [{"prefer-inline": true}]} */}
```ts
import { useState, type ReactNode } from "react";
```

With `considerQueryString`, these two paths are the same module:

{/* file "logo.js" */}
```js logo.js
export const width = 64;
export const height = 64;
```

{/* bad {"options": [{"considerQueryString": true}]} */}
```js
import { width } from "./logo?inline";
import { height } from "./logo.js?inline";
```

And these two aren't:

{/* good {"options": [{"considerQueryString": true}]} */}
```js
import logoUrl from "./logo.svg?url";
import logoText from "./logo.svg?raw";
```
