bugl
bugl
HomeLearnPatternsPathsSearchPremium
HomeLearnPatternsPaths
Learn/TypeScript/TypeScript Core
TypeScript•TypeScript Core

TypeScript Migration Guide

Migrating from JavaScript to TypeScript can significantly improve your codebase's maintainability and developer experience.

This guide will walk you through the process step by step.

Assess Your Codebase

Before starting the migration

  • Identify the size and complexity of your codebase
  • Document the build process and dependencies
  • Check for any existing type definitions ( .d.ts files)
  • Identify critical paths that need special attention

Set Up Version Control

Ensure you have a clean git repository or equivalent:

# Create a new branch for the migration
git checkout -b typescript-migration
# Commit your current state
git add .
git commit -m "Pre-TypeScript migration state"

Install TypeScript

# Install TypeScript as a dev dependency
npm install --save-dev typescript @types/node

Create tsconfig.json

Create a basic tsconfig.json to start with:

{
 "compilerOptions": {
 "target": "ES2020",
 "module": "commonjs",
 "strict": true,
 "esModuleInterop": true,
 "skipLibCheck": true,
 "forceConsistentCasingInFileNames": true,
 "outDir": "./dist",
 "rootDir": "./src"
 },
 "include": ["src/**/*"],
 "exclude": ["node_modules"]
}

Note

Adjust the target based on your minimum supported environments.

Gradual Migration

Migrate one file at a time while keeping the rest as JavaScript.

{
 "compilerOptions": {
 "allowJs": true,
 "checkJs": true
 }
}

Best for: Large codebases, minimal disruption

All-at-Once Migration

Rename all .js files to .ts and fix errors.

# Rename all JS files to TS
find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} \;

Best for: Small to medium projects, greenfield projects

For large projects, we strongly recommend the gradual migration approach to minimize disruption and make the process more manageable.

Start with Configuration

Create a basic tsconfig.json with these recommended settings:

{
 "compilerOptions": {
 "target": "ES2020",
 "module": "commonjs",
 "strict": true,
 "esModuleInterop": true,
 "skipLibCheck": true,
 "forceConsistentCasingInFileNames": true,
 "outDir": "./dist",
 "rootDir": "./src",
 "allowJs": true,
 "checkJs": true,
 "noEmit": true
 },
 "include": ["src/**/*"],
 "exclude": ["node_modules", "dist"]
}

Enable Type Checking for JavaScript

Add // @ts-check to the top of your JavaScript files to enable type checking:

// @ts-check
/** @type {string} */
const name = 'John';
// TypeScript will catch this error
name = 42; // Error: Type '42' is not assignable to type 'string'

Note

You can disable type checking for specific lines using // @ts-ignore .

Rename Files to .ts

Start with non-critical files and rename them from .js to .ts :

# Rename a single file
mv src/utils/helpers.js src/utils/helpers.ts
# Or rename all files in a directory (use with caution)
find src/utils -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} \;

Add Type Annotations

Gradually add type annotations to your code:

// Before
function add(a, b) {
 return a + b;
}
// After
function add(a: number, b: number): number {
 return a + b;
}
// With interface
interface User {
 id: number;
 name: string;
 email?: string;
}
function getUser(id: number): User {
 return { id, name: 'John Doe' };
}

Update Build and Test Scripts

Modify your package.json to include TypeScript compilation:

{
 "scripts": {
 "build": "tsc",
 "dev": "tsc --watch",
 "test": "jest"
 }
}

Note

Make sure to update your test configuration to work with TypeScript files.

ts-migrate

Automated tool for migrating JavaScript to TypeScript

npx ts-migrate-full .

GitHub Repository

TypeStat

Converts JavaScript to TypeScript with type safety

npx typestat

GitHub Repository

@types Packages

Install type definitions for your dependencies

npm install --save-dev @types/react @types/node

TypeSearch

Start Small and Iterate

  • Begin with utility functions and non-UI components
  • Migrate one file or module at a time
  • Commit after each successful migration step

Leverage TypeScript Features

Example

// Use type inference where possible
const name = 'John'; // TypeScript infers 'string'
const age = 30; // TypeScript infers 'number'
// Use union types for flexibility
type Status = 'active' | 'inactive' | 'pending';
// Use type guards for runtime checks
function isString(value: any): value is string {
 return typeof value === 'string';
}

Handle Third-Party Libraries

  • Install @types packages for your dependencies
  • Create declaration files for libraries without types
  • Use declare module for global type extensions

Dynamic Properties

Problem: JavaScript often uses objects as dictionaries.

Example

// Before
const user = {};
user.name = 'John'; // Error: Property 'name' does not exist

Solution: Use index signatures or type assertions.

Example

// Option 1: Index signature
interface User {
 [key: string]: any;
}
const user: User = {};
user.name = 'John'; // OK
// Option 2: Type assertion
const user = {} as { name: string };
user.name = 'John'; // OK

Handling this Context

Problem: this binding issues in callbacks.

Example

class Counter {
 count = 0;
 increment() {
 setTimeout(function() {
 this.count++; // Error: 'this' is not defined
 }, 1000);
 }
}

Solution: Use arrow functions or bind this .

Example

// Solution 1: Arrow function
setTimeout(() => {
 this.count++; // 'this' is lexically scoped
}, 1000);
// Solution 2: Bind 'this'
setTimeout(function(this: Counter) {
 this.count++;
}.bind(this), 1000);

Conclusion

Migrating from JavaScript to TypeScript is a significant but rewarding investment in your codebase.

By following this guide, you can make the transition smoothly and incrementally.

  • Start with a solid tsconfig.json configuration
  • Use allowJs and checkJs for gradual migration
  • Leverage TypeScript's type system to catch errors early
  • Update your build and test processes to support TypeScript
  • Address common challenges with the patterns shown above

Remember that migration is a process, not an event.

It's okay to have a mixed codebase during the transition period.

The important thing is to keep making progress while maintaining code quality.

Ready to Start Your Migration?

Begin by setting up TypeScript in your project and gradually adding type annotations.

The TypeScript compiler will guide you through the process of making your code more robust and maintainable.

For more information, check out the official TypeScript migration guide .

Previous

TypeScript in JavaScript Projects (JSDoc)

Next

TypeScript Error Handling

This chapter

Overview
40

Lessons

241m

Read time

1. TypeScript Tutorial2. TypeScript Introduction3. TypeScript Getting Started4. TypeScript Simple Types5. TypeScript Explicit Types and Inference6. TypeScript Special Types7. TypeScript Arrays8. TypeScript Tuples9. TypeScript Object Types10. TypeScript Enums11. TypeScript Type Aliases and Interfaces12. TypeScript Union Types13. TypeScript Functions14. TypeScript Casting15. TypeScript Classes16. TypeScript Basic Generics17. TypeScript Utility Types18. TypeScript Keyof19. TypeScript Null & Undefined20. TypeScript Definitely Typed21. TypeScript 5.x Updates22. TypeScript Configuration23. TypeScript with Node.js24. TypeScript with React25. TypeScript Tooling26. TypeScript Advanced Types27. TypeScript Type Guards28. TypeScript Conditional Types29. TypeScript Mapped Types30. TypeScript Type Inference31. TypeScript Literal Types32. TypeScript Namespaces33. TypeScript Index Signatures34. TypeScript Declaration Merging35. TypeScript Async Programming36. TypeScript Decorators37. TypeScript in JavaScript Projects (JSDoc)38. TypeScript Migration Guide39. TypeScript Error Handling40. TypeScript Best Practices

On this page

Assess Your CodebaseSet Up Version ControlInstall TypeScriptCreate tsconfig.jsonGradual MigrationAll-at-Once MigrationStart with ConfigurationEnable Type Checking for JavaScriptRename Files to .tsAdd Type AnnotationsUpdate Build and Test Scriptsts-migrateTypeStat@types PackagesStart Small and IterateLeverage TypeScript FeaturesHandle Third-Party LibrariesDynamic PropertiesHandling this ContextConclusionReady to Start Your Migration?