TypeScript MIT

ts-prune

Find unused exports in a typescript project. 🛀

N

nadeesha

Dernière activité 21 sept. 2026
nadeesha/ts-prune

2,1 k

étoiles

67

forks

0

issues ouvertes

typescriptutility

Ce README est souvent en anglais.

ts-prune

CI npm version Monthly downloads Node.js requirement License: MIT

Find potentially unused exports in your TypeScript project. ts-prune reads your tsconfig.json and reports exports with no detected use elsewhere in the project. It reports findings without changing your files.

Requirements

Node.js 22.18 or newer and a TypeScript project with a tsconfig.json. JavaScript files are supported when allowJs is enabled in that configuration.

Quick start

Install with your package manager:

npm install --save-dev ts-prune
# or
yarn add --dev ts-prune
# or
pnpm add --save-dev ts-prune

Run from your project root:

npx ts-prune

For a different TypeScript configuration:

npx ts-prune --project tsconfig.build.json

Example

Given src/math.ts:

export const add = (a: number, b: number) => a + b;
export const subtract = (a: number, b: number) => a - b;
export const multiply = (a: number, b: number) => a * b;

And src/app.ts:

import { add } from './math';
console.log(add(2, 3));

ts-prune reports:

src/math.ts:2 - subtract
src/math.ts:3 - multiply

Each line is file:line - exportName. Exports referenced within their own file are marked (used in module); use --unusedInModule to hide them. Re-exports may show undefined as the line number when the declaration is in another file.

CLI options

Option Description Example
-p, --project [path] TypeScript configuration; defaults to tsconfig.json ts-prune -p tsconfig.build.json
-i, --ignore [regexp] Hide matching output lines ts-prune -i 'test|spec'
-s, --skip [regexp] Exclude matching files from analysis and from references counted as uses ts-prune -s '\.test\.ts$'
-e, --error Exit with status 1 if any findings remain after filtering ts-prune -e
-u, --unusedInModule Hide exports marked (used in module) ts-prune -u
-h, --help Show help ts-prune -h

--ignore filters the report; --skip changes the analysis. For example, skipping tests allows exports used only by tests to appear as unused. Patterns are JavaScript regular expressions, not globs.

Without --error, findings do not cause a nonzero exit status. Configuration and execution errors still fail the command.

Configuration

Create .ts-prunerc.json:

{
  "project": "tsconfig.build.json",
  "ignore": "components/(Button|Input)",
  "skip": "\\.test\\.|test/",
  "unusedInModule": false
}

Or use the ts-prune property in package.json:

{
  "ts-prune": {
    "project": "tsconfig.build.json",
    "error": true
  }
}

Configuration discovery also supports .ts-prunerc (JSON or YAML), .ts-prunerc.yaml, .ts-prunerc.yml, and JS, CJS, or TS configuration files such as .ts-prunerc.cjs:

module.exports = {
  project: 'tsconfig.build.json',
  unusedInModule: true,
};

Use export default in TypeScript configuration files. Discovery starts in the working directory and searches parent directories until it reaches the home directory or filesystem root. Within a directory, the ts-prune property in package.json takes precedence over the standard configuration files. Project paths are resolved from the working directory.

Options are applied in this order: defaults, discovered configuration, explicitly supplied CLI options. In configuration files, use booleans for error and unusedInModule; false disables them. Legacy string values remain accepted, but the string "false" does not disable a flag.

Ignoring an export

Place // ts-prune-ignore-next immediately before its declaration:

// ts-prune-ignore-next
export interface PublicApi {
  name: string;
}

Files explicitly listed in the selected tsconfig's files array are treated as public entrypoints: their exports are excluded from the report. Files selected through include are analyzed normally.

Using ts-prune in CI

Add a script to package.json:

{
  "scripts": {
    "deadcode": "ts-prune --error"
  }
}

Run npm run deadcode in CI to fail when findings remain. Add --unusedInModule if you only want exports without detected local uses.

Limitations

Review findings before deleting code:

  • Frameworks and build tools may consume exports through conventions or reflection that ts-prune cannot detect.
  • Imports with computed paths cannot reliably be resolved. Resolved literal dynamic imports, such as import('./module'), conservatively mark all exports in that module as used.
  • Namespace uses that cannot be tracked, side-effect imports, and wildcard re-exports can keep unused exports out of the report.
  • Uses outside the configured project are not visible. Mark public entrypoints or ignore exports consumed elsewhere.

Development

Use the Node version in .nvmrc:

nvm install
nvm use
npm ci
npm run check           # lint, strict type checks, build, all tests
npm run test:unit
npm run test:integration
npm run test:coverage   # Node's built-in coverage report
npm run test:package    # install a tarball and check its CLI and API
npm run lint:fix        # apply lint fixes

Tests use node:test and node:assert/strict. Test compilation goes into .test-build/; the published CLI and CommonJS library are built into lib/. Integration tests run in temporary directories without global npm links. Coverage measures compiled source in test workers; CLI subprocess behavior is checked separately. The package smoke test installs production dependencies from npm into a temporary consumer project.

Development uses Node 26. CI tests Node 22, 24, and 26 on Linux and Node 26 on macOS and Windows. It runs on pull requests, pushes to master and codex/**, and version tags. Publishing is manual: choose Actions → Release → Run workflow and enter an existing version tag. The release reruns the full matrix before publishing; pushes and tags alone do not publish. See PUBLISHING.md for setup and release steps.

The build uses TypeScript 6.0.3 while the TypeScript ESLint parser requires a compiler version below 6.1. TypeScript 7 is deferred until the parser supports it. The analyzer uses the compiler bundled with ts-morph independently. Runtime dependencies are ts-morph and cosmiconfig. See MODERNIZATION.md for dependency counts and verification results.

Acknowledgements

Built with ts-morph and inspired by @dsherret's approach.

Contributors

Nadeesha
Nadeesha Cabral
Snyk
Snyk bot
Dan
Dan Vanderkam
Josh
Josh Ghoulberg 👻
Vitaly
Vitaly Iegorov
Simon
Simon Jang
The
The Gitter Badger
Tim
Tim Bodeit
Tim
Tim Saunders
Torkel
Torkel Rogstad
Victor
Victor Nogueira
William
William Candillon
curtvict/
curtvict
phiresky/
phiresky
Reece
Reece Daniels
Mikhail
Mikhail Belyaev
Jacob
Jacob Bandes-Storch
Ivo
Ivo Raisr
Hugo
Hugo Duprat
Davis
Davis Ford
David
David Graham
Caleb
Caleb Peterson
Ashok
Ashok Argent-Katwala
Amir
Amir Arad

Project status

This project has been resurrected after a long hiatus. Many projects still depend on ts-prune, and by now it seems to be encoded in AI model weights too. It needs to keep working.

Projets similaires

✂️ Find unused files, dependencies and exports in your JavaScript and TypeScript projects. Knip it before you ship it!

TypeScriptdeadcodedependency-analysisdependency-management
Wwebpro-nl
12,4 k étoiles504

A collection of essential TypeScript types

TypeScriptnpm-packagetypestypescript
Ssindresorhus
17,4 k étoiles742

🔩 The missing TypeScript utils

TypeScriptdenohacktoberfestnode
Ggarronej
480 étoiles7