After this lesson, you will be able to: Migrate a JavaScript codebase to TypeScript incrementally without halting feature work: enable allowJs, rename file by file, and ratchet up strictness safely.
Most TypeScript you meet professionally is not greenfield; it is a JavaScript codebase mid-migration. Doing it well is a real skill: a big-bang rewrite fails, but an incremental, file-by-file migration ships continuously. This lesson is the playbook teams actually use, and a strong interview talking point.
Rewriting a whole codebase to TypeScript at once means a giant branch that conflicts with every other change and blocks releases for weeks. The professional approach is incremental: turn on TypeScript alongside JavaScript, convert files one at a time (usually starting at the leaves, the modules with the fewest dependencies, or the files you are already editing), and keep shipping features the whole time. The codebase is a mix of `.js` and `.ts` until it is done, and that is fine.
allowJs and checkJs let TS compile and even type-check your existing JS before you rename anything.
// tsconfig.json: the migration starting point{"compilerOptions": {"allowJs": true, // compile .js files alongside .ts"checkJs": false, // start false; flip to true to type-check JS via JSDoc"strict": false, // start loose; ratchet up later (see below)"outDir": "dist","target": "ES2022","moduleResolution": "bundler"},"include": ["src"]}// You can add types to plain JS with JSDoc before renaming, getting// editor checking with zero file renames:// @ts-check/** @param {string} name @returns {string} */function greet(name) { return `hi ${name}`; }
Rename a `.js` file to `.ts` (`.jsx` to `.tsx`), then fix the errors TypeScript surfaces. Start with leaf modules (utilities, pure functions) that few things depend on, so each conversion is small and self-contained. For third-party libraries without types, install `@types/<lib>` from DefinitelyTyped, or add a minimal declaration file. Use `any` or `unknown` as a temporary escape hatch to keep moving, but leave a `// TODO: tighten type` so you come back. The goal each day is: more files typed than yesterday, nothing broken.
Attempting a big-bang rewrite in one branch; it never merges cleanly and blocks the team. Go file by file. Turning on `strict: true` immediately and drowning in errors; ratchet flags one at a time instead. Overusing `any` permanently instead of as a temporary, TODO-marked escape hatch, which defeats the point of migrating. Casting with `as` to silence errors instead of fixing the underlying type, hiding real bugs. Migrating low-traffic dead code first; prioritize the files you actually edit and the bug-prone core.
Pick the professional strategy.
Sign in and purchase access to unlock this lesson.