33.7 Measuring Progress: Counting any Usages and Coverage

Right, so you’ve started the migration. You’ve got tsc running, you’ve silenced the most egregious errors with a few any bandaids, and now you’re staring at a question: “Are we there yet?” The answer, my friend, is almost certainly “no,” but we can at least figure out how far away ’there’ is. We need metrics that tell a true story, not a fairy tale. Relying on the TypeScript compiler’s error count is like measuring a road trip by how many times you’ve screamed at other drivers—dramatic but not terribly useful. Let’s talk about real, actionable metrics.

33.6 Automating Migration with ts-migrate and TypeScript-Migrate

Right, so you’ve decided to stop living in the wild west of JavaScript and put on the structured, slightly-constricting-but-in-a-good-way suit of TypeScript. Good for you. Doing this by hand for a large codebase is a special kind of masochism I don’t recommend. This is where automation tools like ts-migrate (from Airbnb) and typescript-migrate (a similar concept) come in. They’re not magic wands, but they’re the closest thing we have to a bulldozer that can clear the initial path. Think of them as your over-caffeinated intern who does 80% of the grunt work incredibly fast, but you absolutely must check their work before you ship it.

33.5 Using @ts-ignore and @ts-expect-error as Temporary Suppressions

Alright, let’s talk about the duct tape and baling wire of your TypeScript migration: @ts-ignore and its slightly more responsible cousin, @ts-expect-error. You’re going to use these. I’ve used them. We all have. They are the temporary barricades you throw up against the tsunami of red squiggles so you can actually compile your code and keep the business running while you methodically fix things. The key word here is temporary. Think of them as a “Check Engine” light you’re actually going to get around to fixing, not one you just put a piece of electrical tape over.

33.4 Dealing with Untyped Dependencies During Migration

Right, so you’ve started wrapping your own code in types, feeling that sweet, sweet intellisense flow, and then you hit this wall: import someLibrary from 'that-old-untyped-package'. Suddenly, your beautifully typed file is awash in any. It’s like meticulously cleaning your house only to have your roommate drag in a muddy dog. Don’t panic. This is a rite of passage. We’re going to tame that muddy dog, or at least build it a very specific shed so it doesn’t track mud everywhere.

33.3 Renaming Files: .js to .ts One Module at a Time

Right, let’s get our hands dirty. We’re not doing a big-bang rewrite where you rename every single file at once and pray for the best. That’s a fantastic way to ruin your entire weekend. Instead, we’re going to do this surgically, one module at a time. This is the “eat the elephant one bite at a time” strategy, except the elephant is your technical debt and we have a very precise fork.

33.2 Adding tsconfig.json to an Existing Project

Right, let’s get this party started. You’ve got a sprawling JavaScript project, and you’ve decided to inject some sanity into it with TypeScript. The very first, and arguably most important, step is to drop a tsconfig.json file in the root of your project. This file is the mission control for the TypeScript compiler (tsc); it tells it exactly how to behave, what files to look at, and how strictly to judge your life choices. Think of it less as a configuration file and more as a rulebook you get to write for your new, more disciplined coding life.

33.1 The Incremental Migration Strategy: allowJs and checkJs

Right, so you’ve decided to stop living in the wild west of JavaScript and put on the structured, slightly-stiff-but-incredibly-warm jacket of TypeScript. Good choice. But you’re not about to stop the entire product roadmap, lock the team in a basement for six months, and rewrite 200,000 lines of code in one go. That’s a fantastic way to get fired, or at the very least, develop a nervous twitch. We’re going to be smart about this. We’re going to use TypeScript’s built-in escape hatches and incremental flags. This isn’t an all-or-nothing proposition. The two key players in this strategy are allowJs and checkJs. Think of them as the training wheels and the slightly anxious parent running behind the bike, respectively.

— joke —

...