typescript-performance-best-practices
TypeScript performance optimization guidelines for build times, type-checking, declaration emit, and editor responsiveness. This skill should be used when writing, reviewing, or optimizing TypeScript code and tsconfig settings. Triggers on tasks involving slow builds, slow type-checking, CI timeouts, editor lag, tsserver memory issues, monorepo configuration, project references, incremental builds, declaration emit, or any TypeScript performance investigation.
SKILL.md
| Name | typescript-performance-best-practices |
| Description | TypeScript performance optimization guidelines for build times, type-checking, declaration emit, and editor responsiveness. This skill should be used when writing, reviewing, or optimizing TypeScript code and tsconfig settings. Triggers on tasks involving slow builds, slow type-checking, CI timeouts, editor lag, tsserver memory issues, monorepo configuration, project references, incremental builds, declaration emit, or any TypeScript performance investigation. |
name: typescript-performance-best-practices description: TypeScript performance optimization guidelines for build times, type-checking, declaration emit, and editor responsiveness. This skill should be used when writing, reviewing, or optimizing TypeScript code and tsconfig settings. Triggers on tasks involving slow builds, slow type-checking, CI timeouts, editor lag, tsserver memory issues, monorepo configuration, project references, incremental builds, declaration emit, or any TypeScript performance investigation.
TypeScript Performance Best Practices
Comprehensive performance optimization guide for TypeScript codebases. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
When to Apply
Reference these guidelines when:
- Writing or refactoring TypeScript code
- Tuning build times, type-checking performance, declaration emit, or editor responsiveness
- Investigating performance regressions
- Reviewing code for performance issues
- Configuring tsconfig.json for new projects or monorepos
Quick Diagnostic Workflow
When TypeScript feels slow, follow this diagnostic sequence:
# Step 1: Get baseline metrics
tsc --extendedDiagnostics --noEmit
# Key metrics to check:
# - Files: Should match expected source count
# - Check time: Usually the bottleneck (>10s is high)
# - Instantiations: High count indicates complex generics
# Step 2: If file count is high
tsc --listFiles | wc -l
tsc --explainFiles 2>&1 | grep -v "@types" | head -50
# Step 3: If Check time is high
tsc --generateTrace ./trace --noEmit
# Open chrome://tracing and load trace/trace.json
# Step 4: If module resolution is slow
tsc --traceResolution 2>&1 | head -200
Rule Categories by Priority
| Priority | Category | Impact | Quick Win |
|---|---|---|---|
| 1 | Build Graph & Incremental | CRITICAL | Enable incremental: true |
| 2 | Program Scope & Inputs | HIGH | Narrow include patterns |
| 3 | Module Resolution & Imports | HIGH | Use moduleResolution: "bundler" |
| 4 | Type Acquisition & Lib Checks | MEDIUM-HIGH | Enable skipLibCheck: true |
| 5 | Type System Complexity | CRITICAL | Annotate function return types |
| 6 | Declaration Emit & Public API | MEDIUM-HIGH | Enable isolatedDeclarations |
| 7 | Editor/tsserver Performance | MEDIUM-HIGH | Use project references |
| 8 | Diagnostics & Profiling | DIAGNOSTIC | Run tsc --extendedDiagnostics |
Common Scenarios
Scenario: Slow CI Builds (>60s)
Symptoms: CI takes minutes, incremental doesn't help
Diagnostic:
tsc --extendedDiagnostics --noEmit
# Check: Files count, Check time, Memory used
Likely fixes:
- Enable
incremental: truewith cached.tsbuildinfo - Enable
skipLibCheck: true(10-50% improvement) - Split into project references (60-70% memory reduction)
- Narrow
includepatterns
Scenario: Slow Editor/IntelliSense
Symptoms: Autocomplete lags, hover takes seconds, high memory
Diagnostic:
# Check tsserver memory
ps aux | grep tsserver | awk '{print $6/1024 " MB"}'
Likely fixes:
- Enable
disableReferencedProjectLoad: true - Enable
disableSolutionSearching: true - Enable
disableSourceOfProjectReferenceRedirect: true - Split into project references
Scenario: Type Checking Takes >10s
Symptoms: Check time dominates in diagnostics
Diagnostic:
tsc --generateTrace ./trace --noEmit
# Open chrome://tracing, find slow checkSourceFile operations
Likely fixes:
- Add explicit return type annotations to exported functions
- Simplify large unions (50+ members)
- Replace deep intersections with interface extension
- Name complex types with type aliases
Scenario: Unexpected Files in Build
Symptoms: More files than expected, node_modules source compiled
Diagnostic:
tsc --explainFiles 2>&1 | grep -v "@types" | grep "node_modules"
Likely fixes:
- Add
"exclude": ["node_modules", "dist"] - Narrow
includeto["src"] - Remove broad
**/*patterns
Quick Reference
1. Build Graph & Incremental (CRITICAL)
Impact: 50-80% faster rebuilds; essential for monorepos
| Rule | Impact | Description |
|---|---|---|
build-project-references | CRITICAL | Split large repos into referenced projects |
build-composite | CRITICAL | Enable composite for project reference builds |
build-incremental | CRITICAL | Reuse prior type-checking work |
build-tsbuildinfo | HIGH | Cache incremental state in stable location |
build-tsc-build | HIGH | Use tsc --build for reference graphs |
build-assume-direct-deps | MEDIUM | Speed up watch in very large repos |
2. Program Scope & Inputs (HIGH)
Impact: Reduces files parsed; every extra file costs time
| Rule | Impact | Description |
|---|---|---|
scope-tight-include | HIGH | Restrict include to source directories |
scope-exclude-build-output | HIGH | Exclude dist/build/node_modules |
scope-avoid-broad-globs | MEDIUM-HIGH | Avoid **/* in large repos |
scope-use-files-array | MEDIUM | Explicit file lists for small packages |
scope-separate-tests | MEDIUM | Keep tests in separate tsconfig |
3. Module Resolution & Imports (HIGH)
Impact: Reduces resolution overhead; wrong mode = excessive lookups
| Rule | Impact | Description |
|---|---|---|
resolve-moduleResolution-modern | HIGH | Use node16/nodenext/bundler |
resolve-bundler-mode | HIGH | Use bundler mode for bundled apps |
resolve-keep-paths-tight | MEDIUM-HIGH | Avoid catch-all paths patterns |
resolve-use-packagejson-exports | MEDIUM | Use package.json exports/imports |
resolve-baseurl-minimize | MEDIUM | Use baseUrl only when needed |
4. Type Acquisition & Lib Checks (MEDIUM-HIGH)
Impact: 10-50% faster type-checking; skips redundant work
| Rule | Impact | Description |
|---|---|---|
types-limit-types | MEDIUM-HIGH | Include only needed @types |
types-restrict-typeRoots | MEDIUM | Limit global type search paths |
types-skip-lib-check | HIGH | Skip .d.ts validation (major win) |
types-typeacquisition-control | MEDIUM | Control automatic type acquisition |
types-disable-filename-based-acquisition | LOW | Prevent filename-based type downloads |
5. Type System Complexity (CRITICAL)
Impact: Complex types cause O(n^2) checking; simplification = big wins
| Rule | Impact | Description |
|---|---|---|
type-annotate-exports | CRITICAL | Named exported types reduce emit cost |
type-annotate-returns | CRITICAL | Return annotations reduce inference |
type-name-complex-types | HIGH | Named types reduce expansions |
type-avoid-deep-intersections | HIGH | Interfaces 4x faster than intersections |
type-avoid-large-unions | HIGH | Large unions cause O(n*m) checking |
type-export-named-types | MEDIUM-HIGH | Named exports reduce .d.ts size |
6. Declaration Emit & Public API (MEDIUM-HIGH)
Impact: Up to 3x faster with isolatedDeclarations; parallel emit
| Rule | Impact | Description |
|---|---|---|
dts-emit-declaration-only | MEDIUM-HIGH | Skip JS emit when bundler handles it |
dts-declarationDir | MEDIUM | Organize .d.ts output separately |
dts-strip-internal | MEDIUM | Remove @internal from .d.ts |
dts-isolated-declarations | CRITICAL | Enable parallel .d.ts emit |
dts-noCheck-fast-emit | HIGH | Skip type-check for .d.ts emit |
7. Editor/tsserver Performance (MEDIUM-HIGH)
Impact: ~3GB to <1GB memory; faster startup, navigation
| Rule | Impact | Description |
|---|---|---|
tsserver-disable-referenced-project-load | MEDIUM-HIGH | Load projects on demand |
tsserver-disable-solution-searching | MEDIUM-HIGH | Stop upward config search |
tsserver-disable-source-redirect | MEDIUM-HIGH | Use .d.ts across boundaries |
tsserver-use-project-references | HIGH | Split projects for memory savings |
tsserver-solution-config | MEDIUM-HIGH | Root tsconfig with files:[] |
8. Diagnostics & Profiling (DIAGNOSTIC)
Purpose: Tools for finding performance issues, not optimizations themselves
| Rule | Purpose | When to Use |
|---|---|---|
diag-extended-diagnostics | Detailed timing breakdown | First diagnostic to run |
diag-diagnostics | Quick timing overview | CI summaries |
diag-explain-files | Why files are included | Unexpected file count |
diag-trace-resolution | Module resolution steps | "Cannot find module" errors |
diag-generate-trace | Chrome DevTools trace | Deep type-checking analysis |
diag-list-files | All files in compilation | Scope audits |
Recommended Base Configuration
For most TypeScript projects:
{
"compilerOptions": {
// Performance essentials
"incremental": true,
"skipLibCheck": true,
"moduleResolution": "bundler",
// For libraries
"declaration": true,
"declarationMap": true,
"isolatedDeclarations": true,
// Standard strictness
"strict": true,
"noUncheckedIndexedAccess": true,
// Output
"target": "ES2022",
"module": "ESNext"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
For monorepos, add to each package:
{
"compilerOptions": {
"composite": true,
"disableReferencedProjectLoad": true,
"disableSolutionSearching": true,
"disableSourceOfProjectReferenceRedirect": true
}
}
How to Use
Read individual rule files for detailed explanations and code examples:
rules/build-project-references.md
rules/type-annotate-returns.md
rules/diag-generate-trace.md
Each rule file contains:
- Impact rating with quantified description
- Why it matters with numbered benefits
- Incorrect/Correct code examples
- When NOT to apply (important for avoiding over-optimization)
- Common mistakes to avoid
- Diagnostic commands for verification
- References to official documentation