Find potentially unused exports in your TypeScript project with zero configuration.
ts-prune is now in maintenance mode - For new projects, we recommend knip which carries forward the same mission with more features.
ts-prune will continue to receive:
- โ Critical bug fixes
- โ Security updates
- โ Dependency maintenance
We will not be adding new features or accepting feature PRs. The tool remains stable and production-ready for existing users.
ts-prune is a simple, fast tool that finds exported TypeScript/JavaScript code that isn't being used anywhere in your project. It helps you:
- ๐งน Clean up dead code - Remove exports that serve no purpose
- ๐ฆ Reduce bundle size - Eliminate unused code from your builds
- ๐ Improve code quality - Keep your codebase lean and maintainable
- โก Zero configuration - Works out of the box with any TypeScript project
# npm
npm install --save-dev ts-prune
# yarn
yarn add --dev ts-prune
# pnpm
pnpm add --save-dev ts-prune# Run in your project root
npx ts-pruneExample output:
src/components/Button.ts:15 - ButtonVariant
src/utils/helpers.ts:8 - formatCurrency
src/types/user.ts:12 - UserRole
src/api/client.ts:45 - ApiResponse
Each line shows: file:line - exportName
Given these files:
// src/utils/math.ts
export const add = (a: number, b: number) => a + b;
export const subtract = (a: number, b: number) => a - b; // unused
export const multiply = (a: number, b: number) => a * b; // unused
// src/app.ts
import { add } from './utils/math';
console.log(add(2, 3));Running ts-prune outputs:
src/utils/math.ts:2 - subtract
src/utils/math.ts:3 - multiply
Use // ts-prune-ignore-next to ignore specific exports:
// src/api/types.ts
export interface User {
id: string;
name: string;
}
// ts-prune-ignore-next
export interface AdminUser extends User { // ignored by ts-prune
permissions: string[];
}
export interface Customer { // will be flagged if unused
customerId: string;
}ts-prune works with various TypeScript patterns:
// Default exports
export default class MyClass {}
// Named exports
export const myFunction = () => {};
export type MyType = string;
export interface MyInterface {}
// Re-exports
export { SomethingElse } from './other-file';
export * from './barrel-file';ts-prune [options]| Option | Description | Example |
|---|---|---|
-p, --project |
Path to tsconfig.json | ts-prune -p tsconfig.build.json |
-i, --ignore |
Ignore pattern (RegExp) | ts-prune -i "test|spec" |
-s, --skip |
Skip files pattern | ts-prune -s "\.test\.ts$" |
-e, --error |
Exit with error code if unused exports found | ts-prune -e |
-u, --unusedInModule |
Skip exports marked as "used in module" | ts-prune -u |
Create .ts-prunerc (JSON), .ts-prunerc.js, or add to package.json:
{
"ignore": "components/(Button|Input)",
"skip": "\\.test\\.|test/",
"project": "tsconfig.build.json"
}Add to your package.json:
{
"scripts": {
"deadcode": "ts-prune",
"deadcode:ci": "ts-prune --error"
}
}{
"husky": {
"hooks": {
"pre-commit": "ts-prune --error"
}
}
}ts-prune | wc -l# Ignore test files
ts-prune | grep -v "\.test\."
# Only show specific directories
ts-prune | grep "src/components"
# Ignore multiple patterns
ts-prune | grep -v -E "(test|spec|stories)"ts-prune categorizes exports into different types:
- Regular unused export:
src/file.ts:10 - exportName - Used in module:
src/file.ts:5 - localHelper (used in module)- Export is only used within the same file
- Use
-uflag to ignore these
- Dynamic imports:
import('./dynamic-file')usage might not be detected - String-based imports:
require('module-name')patterns - Framework magic: Some frameworks use exports through reflection
- Configuration files: Exports in config files might appear unused
For these cases, use // ts-prune-ignore-next or configure ignore patterns.
ts-prune is conservative and may show false positives for:
- Dynamically imported modules
- Framework-specific patterns (Angular services, React lazy loading)
- Build tool configurations
Yes! ts-prune works with .js files in TypeScript projects. Ensure your tsconfig.json includes JavaScript files:
{
"compilerOptions": {
"allowJs": true
}
}Built with the excellent ts-morph library and inspired by this approach by @dsherret.