tsr (TypeScript Remove)

repository·main·Indexed 23 days ago

https://github.com/line/tsr

A utility for removing unused code from TypeScript projects. It performs tree-shaking-like analysis on source files to remove unused exports, declarations, and unnecessary imports/modules. It can be used via a CLI or a JavaScript API and integrates with existing tsconfig.json settings to identify unused code based on project entrypoints.

Tokens
3.3K
Snippets
13
Records
22
Agent score
79%

What's inside tsr

  1. How tsr modifies code to remove unused elements

    main

    tsr performs several types of automated cleanup when it detects unused code:

    1. Removing unused exports: If an exported constant is not used anywhere in the project, the export keyword (or the entire declaration) is removed.
    2. Downgrading exports to locals: If an export is unused but the value itself is used within the same file, tsr removes the export keyword to make it a local variable.
    3. Removing unused functions and their dependencies: If a function is unused, tsr removes the function declaration and any local variables that were only used within that function.
    4. Cleaning up imports: When a function or variable is removed, tsr automatically removes the corresponding import statements if they become unnecessary.
    --- src/c.ts
    +++ src/c.ts
    @@ -1,7 +1,1 @@
    -import { cwd } from "node:process";
    -
     export const c = 'c';
    -
     export function f() {
    -    return cwd();
    -}
  2. How tsr differs from TypeScript, ESLint, and Knip

    main

    tsr is a specialized tool for TypeScript projects designed to detect and automatically remove unused code across the entire project scope. It addresses limitations in other tools:

    • vs TypeScript: While compilerOptions.noUnusedLocals warns about unused local declarations, it does not flag exported values even if they are never used elsewhere in the project. tsr detects these unused exports.
    • vs ESLint: ESLint (and plugins like eslint-plugin-unused-imports) can detect unused imports but cannot detect unused exports because ESLint typically operates on a per-file basis. tsr analyzes the whole project to find unused exports and removes them, along with any resulting unused imports.
    • vs Knip: While Knip is a comprehensive tool for unused code and dependencies, tsr is optimized for TypeScript with several advantages:
      • Automatic Code Modification: tsr is designed for deep, comprehensive editing. For example, if an unused function f() is removed, tsr will also remove any local variables (like a2) that were only used by f().
      • Zero Configuration: tsr works out of the box using your existing tsconfig.json, whereas Knip often requires manual configuration.
      • Predictability: tsr relies strictly on TypeScript's module resolution logic. If tsc passes, tsr's logic is predictable.
      • Performance & Size: tsr is significantly smaller (~98kB vs 5.86MB) and faster (approx. 2.14x faster than Knip).
  3. How to skip unused code removal

    main

    If you want to prevent tsr from removing a specific export, add the // tsr-skip comment directly above the declaration.

    // tsr-skip
    export const hello = 'world';
  4. Quick Start with tsr

    main

    To use tsr to find and remove unused code, follow these steps:

    1. Verify tsconfig.json: Ensure your include and exclude settings are correctly configured so tsr can accurately detect the project structure.
    2. Identify Entrypoints: Determine your project's entrypoint files (e.g., src/main.ts) or patterns (e.g., src/pages/*).
    3. Execute: Run tsr using regex patterns that match your entrypoints. Use the --write flag to apply changes directly to your files.

    Note: It is highly recommended to use tsr in a git-controlled environment because the --write flag will delete code.

    npx tsr 'src/main\.ts$'
  5. Run benchmarks for tsr

    main

    To run benchmarks, you must execute all scripts from the benchmark/ directory.

    Prerequisites

    1. Install hyperfine.
    2. Ensure tsr is installed globally via npm: npm i -g tsr.

    Execution

    Run the specific shell script corresponding to the library or project type you wish to benchmark:

    • For react-hook-form:
      ./react-hook-form.sh
    • For taxonomy (Next.js project):
      ./taxonomy.sh
    • For excalidraw:
      ./excalidraw.sh
  6. Use --write to edit files in place with the tsr CLI

    main

    In v1, the tsr CLI defaults to --check mode (checking for unused code without modifying files) to prevent accidental edits. To enable the previous behavior of editing files in place, you must explicitly use the --write flag.

    npx tsr --write 'src/main\.ts$'
  7. Handling test files with tsr

    main

    If your tsconfig.json includes test files, tsr might identify them as unused because they are not referenced by your main entrypoints. To prevent test files from being deleted:

    1. Recommended: Use TypeScript Project References to separate implementation and test configurations.
    2. Workaround: Pass a pattern that matches your test files as an additional entrypoint argument to the CLI.

    Example Workaround:

    npx tsr -w 'src/main\.ts$' '.*\.test\.ts$'
  8. Preventing accidental deletion of test files

    main

    If your tsconfig.json includes test files, tsr might identify them as unused and delete them if they aren't referenced by your entrypoints.

    To prevent this, you can explicitly pass your test file pattern as an entrypoint to ensure they are treated as part of the graph:

    npx tsr -w 'src/main\.ts$' '.*\.test\.ts$'

    Best Practice: The recommended way to handle this is to use TypeScript Project References to separate implementation code from test code in your tsconfig settings.

  9. Migrate the JavaScript API to tsr

    main

    The JavaScript API import path has changed. Replace the old @line/ts-remove-unused import with tsr. For configuration options, refer to import('tsr').Config.

    // before
    import { remove } from '@line/ts-remove-unused';
    
    // after
    import { tsr } from 'tsr';