Migrating a JavaScript project to TypeScript can dramatically improve type safety, developer experience, and maintainability. Here's a step-by-step guide to refactor your JS codebase to TS.
🪜 Step-by-Step Migration Plan
✅ Initialize TypeScript
Add TypeScript to your project:
npm install --save-dev typescript
npx tsc --initThis generates a tsconfig.json file. Start with:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"allowJs": true,
"checkJs": false,
"outDir": "./dist",
"rootDir": "./src",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}📦 Rename Files
Gradually rename .js files to .ts (or .jsx → .tsx for React):
mv src/index.js src/index.tsStart small: maybe one folder or module.
👮 Fix Obvious Type Errors
Once you rename a file, TypeScript will highlight type issues.
Start by:
Adding type annotations to function arguments and return values
Defining interfaces or type aliases
Installing types for dependencies:
npm i -D @types/lodash @types/express @types/react
🧱 Add Type Definitions Gradually
Use any temporarily if you're unsure, then tighten types later.
function getUser(id: any): any {
return fetch(`/api/user/${id}`).then(res => res.json());
}Later replace any with proper types.
🧪 Add JSDoc (Optional Pre-step)
If you're not ready to rename files, add JSDoc for type-checking in JS files:
/** @param {string} name */
function greet(name) {
return `Hello, ${name}`;
}Enable checkJs: true in tsconfig.json to enforce types in JS files.
⚙️ Gradual Type Coverage
Tools like ts-migrate or ts-prune help in large codebases.
Use typescript with tsc --noEmit to just type-check without building.
📁 Refactor to Use Types Fully
Replace:
module.exports→export/export defaultrequire()→importLoose objects → Interfaces/Types
// Before
const user = { name: "Tisha", age: 24 };
// After
interface User {
name: string;
age: number;
}
const user: User = { name: "Tisha", age: 24 };🔄 Migration Strategy
Strategy | Description |
|---|---|
Big Bang | Convert entire project at once (works for small projects) |
Incremental | Convert file by file, gradually increasing type safety |
Hybrid (JSDoc) | Use JSDoc to document types before full conversion |
🧠 Best Practices
Keep
strict: trueintsconfig.jsonfor maximum safetyUse
unknowninstead ofanywhen appropriateAvoid
declare varunless absolutely neededPrefer interfaces for objects, types for unions or complex compositions
Use utility types like
Partial,Pick,Omitto reduce redundancy