94 percent of compile errors in AI-generated code are type errors — that is the finding from GitHub Octoverse 2025. If you let AI assistants loose on an untyped JavaScript codebase, you have disabled exactly the verification layer that catches the most common failure mode of machine-generated code before merge. That makes the TypeScript migration no longer a style debate inside the engineering department, but part of your AI governance: the type system checks every AI suggestion automatically — without a human spending a single minute of review time on it.
The market has already answered the question of whether. According to State of JS 2025, 40 percent of respondents write TypeScript exclusively, and only 6 percent still write plain JavaScript. This guide therefore covers the how — the sequence, the real-world effort, the places where migrations actually fail. And, because honesty is cheaper here than later: the cases where you are better off not migrating at all.
Why now: An untyped codebase is a double risk
The first risk is the classic one. In an untyped codebase, the knowledge of which function expects which data shape lives in the heads of the developers who wrote it. Every backfill hire, every refactoring, every integration turns into archaeology. TypeScript moves that knowledge out of heads and into the compiler — that is the real maintainability gain, not the autocomplete in the editor.
The second risk is new. AI assistants dramatically increase the volume of change in your codebase while human review capacity stays constant. The only control layer that scales with that volume is a machine-driven one — and the 94 percent figure from GitHub Octoverse 2025 shows it works precisely on the dominant error type. That the talent and cost side is consolidating toward TypeScript anyway is something we worked through in our TCO comparison of TypeScript vs. Java; for JavaScript codebases, the logic applies all the more, because the switch does not change the language — it only adds a type system.
Big bang or incremental?
The official migration path is incremental and documented in the TypeScript Handbook: enable allowJs in the compiler configuration, rename files from .js to .ts one at a time, raise strictness step by step. JavaScript and TypeScript coexist in the same project for as long as you like — there is no deadline by which everything has to be done. Big-bang migrations demonstrably work too, but only under conditions the midmarket rarely has: Pinterest migrated roughly 3.7 million lines via codemod in a single pass in 2025 — safeguarded by a byte-for-byte comparison of the transpiled output; Stripe needed months of codemod preparation in 2022 before the one big pull request for a similar scale could be merged. If you do not have a dedicated migration team with that depth of tooling, go incremental. That is not a fallback of convenience — it is the path the vendor designed.
The staged plan: Six stages from allowJs to the CI gate
The following sequence has proven itself in our projects and matches the official path. What matters is that every stage has a measurable finish line — otherwise the migration becomes a permanent condition nobody is steering anymore.
| Stage | Action | Complete when |
|---|---|---|
| 1 — Coexistence setup | Integrate the TypeScript compiler into the build, enable allowJs; not a single file is renamed | The build stays green unchanged and runtime behavior is identical |
| 2 — New files in TypeScript only | Team rule: every new file is created as a TypeScript file; code review enforces it | No new JavaScript files appear in the repository |
| 3 — Legacy code as you touch it | Whoever changes a file for business reasons renames and types it in the same pass | The migration ratio climbs monthly alongside normal feature work — with no dedicated budget |
| 4 — Type boundaries to legacy modules | Define declaration files for not-yet-migrated modules and untyped dependencies | Migrated files no longer import anything unchecked as any |
| 5 — Turn on strict flags in stages | noImplicitAny first, then strictNullChecks, the full strict bundle last | All flags active, the error list is empty, remaining exceptions are documented |
| 6 — CI gate | Type checking blocks merges; the migration ratio is reported as a KPI | Regressions are technically impossible; progress is part of management reporting |
The touch-it-type-it principle in stage 3 is the economic core of the plan: it couples migration work to code that is being touched anyway — meaning places where the team currently has the context in their heads and the typing effort is lowest. Rarely touched, stable modules are deliberately left for last. That is not a blemish, it is prioritization: types pay off most where code changes.
Stage 4 is the most inconspicuous and the one most often skipped — with consequences. As long as migrated files accept their imports from legacy modules unchecked as any, type safety at exactly those boundaries is a promise without backing: the compiler reports green but checks nothing there. Declaration files for the most important legacy modules and untyped dependencies close that gap without touching the legacy code itself — you describe only the public interfaces, not the implementation. As a rule of thumb, we prioritize the modules imported by the largest number of already-migrated files: that is where each line of declaration buys the most safety.
The strict flags in the right order
The most common mistake in stage 5 is activating the full strict bundle immediately. That produces thousands of errors in one blow, the team gets used to red builds, and the migration loses its authority. The order recommended in the Handbook starts with noImplicitAny — the flag with the best ratio of effort to safety gained, because it surfaces silently untyped code. Next comes strictNullChecks, which in our experience finds the most real bugs but also creates the most work. Only at the end comes the complete strict bundle — the umbrella option that activates all strict checks at once. If you enable checkJs in parallel, you get type checking even in JavaScript files that have not been renamed yet — useful as an early-warning system, but optional.
Stage 6 makes the migration fully steerable: type checking blocks merges, and the migration ratio — the share of typed files or lines — moves into regular reporting as a KPI. Progress then no longer depends on memory and goodwill but is measurable like any other technical metric. For you as a decision-maker, this is the point where a developer initiative becomes a program with a KPI, an owner, and a target date — even if that target date deliberately sits far out.
Honest effort: Calendar time is not team time
The most reliable public numbers come from three engineering blogs. Airbnb built the codemod tool ts-migrate in 2020 (now open source) and used it to convert projects with over 50,000 lines and more than 1,000 files in a single day — and was still only at 86 percent of its 6-million-line monorepo at the time of the report, because the migration ran alongside regular work. Stripe converted its largest frontend, 3.7 million lines, in a single pull request in 2022 — after months of codemod preparation. Pinterest handled the same order of magnitude in eight months in 2025, incident-free. So the honest range is: months with a focused, tool-supported approach — years if the migration runs alongside feature work.
Two qualifications belong here. First: Stripe and Pinterest migrated from Flow, an already typed system — their starting point was more favorable than raw JavaScript, where types still have to be worked out. Second: your codebase probably does not have millions of lines. For the midmarket, the relevant metric is therefore not calendar time but team time: with the touch-it-type-it principle, the migration does not tie up a dedicated developer — it spreads as a small surcharge across work that happens anyway. Calendar time gets longer as a result — that is the deliberately chosen price. What you need in return is patience in your reporting: a ratio that climbs from 20 to 80 percent is a success, even if it takes four quarters to get there.
When you should NOT migrate
A guide that only knows the case in favor is sales prose. There are constellations in which the migration does not pay off economically — and a clean no saves more money there than a half-hearted yes. The four most common:
Small, stable codebase: If an application has been running for years, sees hardly any changes, and its error rate is unremarkable, typing buys you almost nothing. Types pay off when code changes — where nothing changes, safeguarding through tests and monitoring is enough.
Short remaining lifespan: If replacing the application is already on the roadmap, every euro belongs in the successor, not in the legacy system. A migration whose result gets shut down before it amortizes is make-work.
Pure configuration and glue scripting: Build scripts, deployment automation, small internal tools — JavaScript is fine here. The governance case from the introduction concerns product code that AI assistants and changing teams will evolve for years.
When the real risk lies elsewhere: If a PHP backend on a version without security patches sits underneath your JavaScript frontend, typing is not your most urgent problem. We have a dedicated guide for that case: Migrating legacy PHP to a TypeScript stack.
The next step
The entry point is deliberately small: stage 1 — the coexistence setup with allowJs — is done in a few days and changes nothing about runtime behavior. After that, it is not technology that decides but discipline: the review rule for new files, the touch-it-type-it principle, the staged strict flags, the CI gate. As a TypeScript agency, we take on exactly that part — from setup through the strict staging to team onboarding, typically in a retainer model for €4,000–12,000 per month, running alongside your feature work.
If you first want to know where your codebase stands: the starting point is our modernization assessment at a fixed price after discovery — inventory, risk picture, staged plan with effort estimate. Details on our software modernization page, or clarify your starting position directly in a free 30-minute call.
As of July 2026. All prices net of VAT. Market figures cited with sources in the text; project prices are published happycoding anchors from real projects.
