Using TypeScript 4.9 with Next.js 12

kgf

Kenneth G. Franqueiro

Posted on February 10, 2023

Using TypeScript 4.9 with Next.js 12

I regularly work in a codebase running on Next.js 12, and recently updated its TypeScript dependency to 4.9, looking forward to being able to take advantage of useful new features such as the satisfies operator.

Unfortunately, the moment I tried to use anything 4.9-specific, things went sideways rather quickly, as the dev server and build command didn't recognize the feature, due to their use of SWC. Since Next.js 12 hasn't had new releases for a while, the accompanying version of SWC is now significantly out-of-date.

This wouldn't be an issue if the codebase were on Next.js 13, but we haven't made the jump yet for a variety of reasons. Fortunately, I was able to overcome this obstacle while remaining on Next.js 12; if you find yourself in a similar situation, hopefully this process can work for you as well.

Version-Pinning SWC

Both npm and yarn provide a way to override installed versions of packages in package.json: npm through the overrides property (only in npm 8 or higher), and yarn through the resolutions property.

Unfortunately, as I found out, yarn's resolutions property has a long history of not playing well with optionalDependencies: anything placed into resolutions is treated as required and will abruptly fail to install if it is, for example, a platform-specific package appropriate for your deploy environment but not your dev environment or vice versa, as is the case here.

Since this particular codebase also relied on yarn, this warranted an impromptu switch to npm to see how overrides would fare. Fortunately, synp exists to migrate between package lockfile formats. (npm also evidently supports yarn.lock files directly, which I only found out after converting, so I didn't put that to the test.)

npm's overrides had no issue working, with the following configuration:

"overrides": {
  "next": {
    "@next/swc-darwin-x64": "13.1.6",
    "@next/swc-linux-x64-gnu": "13.1.6",
    "@swc/helpers": "0.4.14"
  }
}
Enter fullscreen mode Exit fullscreen mode

By forcing the version of relevant platform-specific @next/swc-* packages (in this particular case, OS X for dev and Linux for CI/deployment) to their latest v13 counterparts, and updating @swc/helpers to match the dependency listed in v13, we can get support for TypeScript's new features while still running Next.js 12, and there don't seem to be any adverse side effects.

Other Potential Gotchas

We've tackled the dev server and build process itself above, but other parts of your toolchain may also require updating to support TypeScript 4.9 if they haven't been in a while. Make sure to test all aspects of local development (including your code editor and its extensions), and of course keep an eye on CI processes when merging the update.

I encountered a couple more hiccups:

Jest

The codebase relied on Jest 27, using babel-jest and babel-loader. This similarly ran into issues failing to parse TypeScript 4.9 features. I ended up doing a few things on the way to resolving this:

  • Upgraded to Jest 29
  • Updated a couple of packages (isbot and uuid) to incorporate fixes that resolved errors that would come up in newer versions of Jest
  • Switched from babel-jest and babel-loader to ts-jest (note that this requires a custom tsconfig.json with "jsx": "react", as opposed to Next requiring "jsx": "preserve")

Prettier

In my case, Prettier was still on a rather old version, so I needed to update it to 2.8 in order for next lint to pass, since the codebase uses eslint-plugin-prettier.

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
kgf
Kenneth G. Franqueiro

Posted on February 10, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About