Migrating from JavaScript to TypeScript

The 50,000-Line Codebase Nobody Dared to Touch

March 2021. Our flagship product: 50,127 lines of JavaScript. Built over 4 years. 12 developers. Zero type safety.

The problems were mounting:

  • Production bugs: 15-20 per sprint

  • Refactoring time: 3x longer than it should be

  • Onboarding: New devs took 2 months to be productive

  • Fear factor: Nobody wanted to change core modules

CEO's mandate: "Make this codebase maintainable. We're hiring 8 more engineers."

Converting 50K lines overnight = impossible. Too risky. But doing nothing? Unsustainable.

I proposed gradual migration: TypeScript alongside JavaScript, convert module by module, zero downtime.

Team reaction: "That'll never work."

6 months later: 100% TypeScript. Production bugs down 73%. Refactoring time cut in half. New devs productive in 2 weeks.

Here's how we did it.


The Migration Strategy

Phase 1: Setup (Week 1)

Enable TypeScript without breaking JavaScript:

Install dependencies:

Create first TypeScript file:

Result: TypeScript and JavaScript coexist. Build works. Zero breaking changes.


Phase 2: Convert Utilities First (Weeks 2-3)

Start with pure functions - no dependencies, easy to type.

Before (JavaScript)

After (TypeScript)

Immediate benefit: Found a bug! Original validateEmail accepted null. Now type-safe.


Phase 3: Type the Data Models (Week 4)

Define core types for your domain:

Impact: Now you have a single source of truth for your data structures.


Phase 4: Convert Services Layer (Weeks 5-8)

Business logic next. Uses the types you defined.

Before (JavaScript)

After (TypeScript)

Benefits:

  • Autocomplete everywhere

  • Can't pass wrong data shape

  • Refactoring is safe


Phase 5: Convert API Layer (Weeks 9-12)

Controllers and routes.

Before (JavaScript)

After (TypeScript)


Dealing with any

The biggest trap: using any everywhere.

Bad Migration

Good Migration


Typing Third-Party Libraries

Install Type Definitions

No Types Available?

Create your own:

Or use any temporarily:


Gradual Strictness

Start lenient, tighten over time.

Initial Config

After 50% Migrated

After 80% Migrated


Common Migration Patterns

Pattern 1: Rename & Rebuild

Pattern 2: JS + TS Interop

Pattern 3: Type Definitions First


Testing During Migration

Before

After


Automation Tools

ts-migrate (Airbnb)

Automatically:

  • Renames .js to .ts

  • Adds any types everywhere

  • You clean up the anys

TypeStat

Improves existing TypeScript:

  • Infers better types

  • Fixes common issues


Our Migration Timeline

Week 1: Setup, first .ts file Weeks 2-3: Utils (500 lines) Week 4: Type definitions (all models) Weeks 5-8: Services (15,000 lines) Weeks 9-12: Routes/Controllers (10,000 lines) Weeks 13-16: Frontend components (20,000 lines) Weeks 17-20: Tests migration Weeks 21-24: Strict mode, cleanup

Total: 6 months, zero downtime, 73% fewer bugs.


Your Challenge

Migrate a JavaScript project to TypeScript:


Key Takeaways

  1. Start small - utilities and new code first

  2. Define types early - data models are foundation

  3. Gradual strictness - don't enable strict mode day 1

  4. Avoid any - use unknown or proper types

  5. Install @types - for third-party libraries

  6. Coexistence - JS and TS can work together

  7. Test continuously - don't break existing features

  8. Tools help - ts-migrate, TypeStat automate parts


What I Learned

50,000 lines of JavaScript. Zero type safety. 15-20 bugs per sprint. New devs lost for months.

Management wanted a rewrite. I proposed gradual migration.

6 months later:

  • βœ“ 100% TypeScript

  • βœ“ 73% fewer production bugs

  • βœ“ Refactoring time cut in half

  • βœ“ New devs productive in 2 weeks

  • βœ“ Zero downtime during migration

The secret? Don't migrate everything at once. Start with utilities. Build up types. Convert layer by layer. Run tests continuously.

Before TypeScript, the codebase was fragile. One change could break three unrelated features. Refactoring meant gambling. After TypeScript, changes are predictable. Compiler catches breaks. Refactoring is safe.

The lesson: Big codebases don't need big-bang migrations. They need incremental, tested, type-safe conversions. Start today. One file at a time.

Your JavaScript codebase can be TypeScript in 6 months. Without breaking production.


Next: Best Practices and Patterns

In the next article, we'll cover TypeScript best practices and patterns learned from managing 200,000+ lines of production TypeScript. You'll learn the code review checklist that catches 90% of issues before they merge.

Last updated