typescript
/

TypeScript Performance – Optimize Your Code

Last Sync: Today

On this page

13
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

typescript

TypeScript Performance – Optimize Your Code

Why TypeScript Performance Matters

TypeScript performance affects both compile-time and runtime. Optimizing your TypeScript code leads to faster builds, smaller bundles, and better user experiences.

Compiler Options for Performance

JSONRead-only
1
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM"],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmitOnError": true
  }
}

Project References

Split large codebases into smaller projects to speed up compilation.

JSONRead-only
1
{
  "references": [
    { "path": "./core" },
    { "path": "./utils" },
    { "path": "./components" }
  ]
}

Incremental Builds

TypeScriptRead-only
1
// tsconfig.json
{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo"
  }
}

// Command line
tsc --incremental

Avoiding Type Bloat

TypeScriptRead-only
1
// ❌ Bad - Creates complex inferred types
const config = {
  a: { b: { c: { d: { e: 1 } } } }
};

// ✅ Good - Explicit typing prevents deep inference
interface Config {
  a: {
    b: {
      c: number;
    };
  };
}

const config: Config = {
  a: { b: { c: 1 } }
};

Using const Assertions

TypeScriptRead-only
1
// More specific, narrower types
const routes = {
  home: '/home',
  about: '/about',
  contact: '/contact'
} as const;

// Type is: { readonly home: '/home'; readonly about: '/about'; ... }

Runtime Performance Tips

  • Use primitive types over objects when possible
  • Avoid type assertions that cause runtime checks
  • Minimize spread operators in hot code paths
  • Use Map/Set instead of plain objects for dynamic lookups
  • Debounce/throttle frequent events

Bundle Optimization

TypeScriptRead-only
1
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};

// Use dynamic imports
const HeavyComponent = await import('./HeavyComponent');

Performance Comparison

TechniqueCompile Time ImpactRuntime Impact
Incremental builds⬇️ -70%➖ None
Skip lib check⬇️ -30%➖ None
Const assertions➖ None⬆️ +5%
Project refs⬇️ -50%➖ None

Common Performance Pitfalls

  • Excessive type inference in large objects
  • Overusing mapped types and conditional types
  • Deep nested generics that explode combinatorially
  • Using any type (disables optimization opportunities)
  • Large union types (> 10-20 members)

Profiling TypeScript

BASHRead-only
1
# Generate performance trace
tsc --generateTrace trace

# Analyze with Chrome DevTools or
# https://typescript.azurewebsites.net/trace

# Measure compile time
time tsc --noEmit

# Use TypeScript compiler performance flags
tsc --extendedDiagnostics

Best Practices Summary

  • Enable incremental compilation in CI/CD pipelines
  • Use project references for monorepos
  • Set strict mode to catch errors early
  • Avoid barrel files (index.ts that re-exports many modules)
  • Prefer interfaces over type aliases for object types
  • Use satisfies operator (TS 4.9+) for type-safe inference

Conclusion

TypeScript performance optimization balances compile-time speed, bundle size, and runtime efficiency. Use compiler flags, project references, and type design patterns to keep your TypeScript code fast and maintainable.

Try it yourself

// Measure type inference performance
interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

// ❌ Slow with large unions
type Status = 'pending' | 'active' | 'inactive' | 'deleted' | 'banned' | 'suspended';

// ✅ Fast with enums for many values
enum StatusEnum {
  PENDING = 'pending',
  ACTIVE = 'active',
  INACTIVE = 'inactive',
  DELETED = 'deleted',
  BANNED = 'banned',
  SUSPENDED = 'suspended'
}

// Test performance
const users: User[] = [];
for (let i = 0; i < 1000; i++) {
  users.push({
    id: i,
    name: `User ${i}`,
    email: `user${i}@example.com`,
    createdAt: new Date()
  });
}

console.log(`Created ${users.length} users`);

Test Your Knowledge

Q1
of 4

Which compiler option enables incremental builds?

A
fastBuild
B
cache
C
incremental
D
watchMode
Q2
of 4

What do project references improve?

A
Runtime speed
B
Compilation speed
C
Bundle size
D
Type safety
Q3
of 4

Which operator provides type-safe inference without losing literal types?

A
as const
B
satisfies
C
implements
D
extends
Q4
of 4

What is a common performance pitfall with types?

A
Using primitive types
B
Deep nested generics
C
Using interfaces
D
Explicit typing

Frequently Asked Questions

How to speed up TypeScript compilation?

Use incremental builds, skipLibCheck, and project references.

What is incremental compilation?

Recompiles only changed files instead of the whole project.

Do const assertions improve performance?

They improve type inference but don't affect runtime.

How to profile TypeScript compiler?

Use --generateTrace or --extendedDiagnostics flags.

Previous

ts best practices

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.