import-integrity/no-unused-exports
Ensures exports are imported elsewhere in the package.
Rule Details
no-unused-exports looks at all exports and analyzes who imports them. An export is considered used if it is in an entry point file or externally imported file, or if it is imported by another file in the package.
Examples
Incorrect
/*
.
└── a.ts
*/
// a.ts
export const a = 10;/*
.
├── a.ts
└── __test__/
└── b.ts
*/
// a.ts
export const a = 10;
// __test__/b.ts
import { a } from '../a';Correct
/*
.
└── a.ts
*/
// a.ts
const a = 10;/*
.
├── a.ts
└── b.ts
*/
// a.ts
export const a = 10;
// b.ts
import { a } from './a';/*
.
├── a.ts
└── __test__/
└── b.ts
*/
// a.ts
export interface Foo {
bar: string
}
// __test__/b.ts
import type { Foo } from '../a';Behavior
Test files don't count as usage
Imports from test files don't count as usage for production exports. If a production file's only consumers are tests, the export is reported as unused. If you want to mark an export as deliberately test-only, use the _testOnly prefix instead. no-test-only-imports enforces that exports with that prefix are only imported by tests, so the marker stays accurate (similar to how @ts-expect-error in TypeScript verifies that the suppressed error actually exists, unlike @ts-ignore).
Type imports count as usage
Exports imported with import type (or export type from) satisfy this rule even though they're erased at compile time. The third "correct" example above demonstrates this.
Limitations
.d.ts exports
Exports listed in .d.ts files are not checked. This is intentional for the common case where .d.ts files declare ambient types for third-party modules. The downside: if a .d.ts file declares types for a neighboring .js file and exports types not present in the .js file, those .d.ts-only exports won't be flagged as unused even if they actually are.
Barrel imports
If an export is later imported as part of a barrel, the rule may report a false negative and claim the export is used when it isn't. The barrel object is referenced, and the rule can't follow the object through arbitrary code to determine which specific exports get accessed:
// a.ts
export const a1 = 10;
export const a2 = 10;
// b.ts
import * as a from './a';
console.log(a.a1);In this example, a2 is not used, but the rule can't determine that.
Configuration
Options
This rule has no options.
When not to use this rule
We don't recommend disabling this rule. If you have an export that's deliberately not consumed by the current codebase (e.g. a public API that external code will use), declare it in entryPointFiles or externallyImportedFiles instead.