Find dead exports in TypeScript/JavaScript projects — unused functions, types, and constants you can safely delete.
npx deadcodeNo install required. Scans your src/ directory and shows every exported symbol that is never imported anywhere.
Analyzing files in src/...
Found 34 files.
src/utils/formatters.ts
export function formatBytes (line 12) — never imported
export function formatRelativeTime (line 28) — never imported
src/hooks/useDebounce.ts
export function useDebounce (line 5) — never imported
src/types/legacy.ts
export type LegacyUser (line 3) — never imported
export interface OldApiResponse (line 11) — never imported
5 dead exports in 3 files. Safe to remove.
Note: Dynamic imports and string-based access not detected.
| Flag | Default | Description |
|---|---|---|
--src=<dir> |
src |
Directory to scan |
--ext=<exts> |
.ts,.tsx,.js,.jsx |
Comma-separated extensions |
--include-tests |
off | Include *.test.* / *.spec.* files |
--fail |
off | Exit code 1 if dead exports found (useful in CI) |
--help |
— | Show help |
--version |
— | Show version |
# Scan a different directory
npx deadcode --src=lib
# Only TypeScript files
npx deadcode --ext=.ts,.tsx
# Include test files in analysis
npx deadcode --include-tests
# Fail CI if dead exports exist
npx deadcode --failCreate .deadcoderc.json in your project root:
{
"src": "src",
"extensions": [".ts", ".tsx"],
"includeTests": false,
"ignorePatterns": ["generated", "vendor"],
"ignoreFiles": ["src/polyfills.ts"]
}| Key | Type | Description |
|---|---|---|
src |
string |
Source directory |
extensions |
string[] |
File extensions to scan |
includeTests |
boolean |
Include test files |
ignorePatterns |
string[] |
Regex patterns — matching paths are skipped |
ignoreFiles |
string[] |
File substrings — matching paths are skipped |
CLI flags override .deadcoderc.json values.
name: Dead Code Check
on: [push, pull_request]
jobs:
deadcode:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Check for dead exports
run: npx deadcode --src=src
# Add --fail to block merges when dead exports are introduced:
# run: npx deadcode --src=src --faildeadcode uses pure static analysis — no compiler, no AST library, no dependencies:
- Walk all
.ts/.tsx/.js/.jsxfiles undersrc/ - Extract exports per file using regex patterns:
export function name,export const name,export class nameexport type name,export interface name,export enum nameexport default,export { name },export { name as alias }
- Extract imports per file — every named symbol and its source path
- Resolve relative import paths to absolute file paths
- Cross-reference: any export not found in any import list is flagged
Index files (index.ts, index.tsx, etc.) are excluded from export collection — they are barrel files that typically just re-export everything, and treating them as dead would produce false positives.
- Dynamic imports (
import(variable)) are not detected. If you dynamically import a module using a computed path, those exports will be reported as unused. - String-based access (
obj['methodName'](),require(variable)) is invisible to static analysis. - Barrel file re-exports: If module A exports
foo, barrelindex.tsre-exportsfoo, and your code importsfoofrom the barrel,deadcodewill correctly detect thatfoofromindex.tsis used — butfooinmodule Ais never directly imported. Use the barrel exclusion behavior (index files are skipped for export collection) to handle this. - Type-only imports/exports: Partially supported.
import type { Foo }is recognized, but some edge cases may be missed. - Monorepos:
deadcodeanalyzes one package at a time. Cross-package imports will not be tracked.
| Feature | deadcode | ts-prune | knip |
|---|---|---|---|
| Zero dependencies | ✓ | ✗ (ts compiler) | ✗ |
| TypeScript AST | ✗ (regex) | ✓ | ✓ |
| Accuracy | Good | Better | Best |
| Speed | Very fast | Fast | Moderate |
| Config needed | None | None | Recommended |
| Unused files | ✗ | ✗ | ✓ |
| Unused deps | ✗ | ✗ | ✓ |
| JS support | ✓ | Partial | ✓ |
| npx (no install) | ✓ | ✓ | ✓ |
When to use deadcode: You want a fast, zero-dependency sanity check with no setup. Great for CI scripts and quick audits.
When to use ts-prune: You want TypeScript compiler-level accuracy and are okay with having typescript as a dependency.
When to use knip: You want a comprehensive audit — unused files, unused dependencies, unused exports — and are willing to spend time on configuration.
deadcode uses only Node.js built-ins: fs, path. No node_modules to install, no supply-chain risk, no version conflicts.
MIT