Linter · Rules
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.
Configure
Off by default. To turn it on:
bunfig.toml
[lint.rules]
"import/no-duplicates" = "error" # or "warn"
Every option, set to its default:
bunfig.toml
[lint.rules]
"import/no-duplicates" = ["error", {
prefer-inline = false,
considerQueryString = false,
}]
Examples
Reported:
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { writeFile } from "node:fs/promises";
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);
import { clamp } from "./utils";
import { sum } from "./utils.js";
Not reported:
import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
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. |
import { useState } from "react";
import type { ReactNode } from "react";
import { useState, type ReactNode } from "react";
With considerQueryString, these two paths are the same module:
logo.js
export const width = 64;
export const height = 64;
import { width } from "./logo?inline";
import { height } from "./logo.js?inline";
And these two aren't:
import logoUrl from "./logo.svg?url";
import logoText from "./logo.svg?raw";