next.js: Typescript `next dev` error reporting

Feature request

Describe the feature

When I run next dev and introduce a TypeScript type error on an active page, I expect to see a TypeScript error printed out in my terminal. This matches what the docs say:

By default, Next.js reports TypeScript errors during development for pages you are actively working on.

(From https://nextjs.org/docs/basic-features/typescript)

This works as expected in 9.3.6 but does not work in 9.4.0 or above. (I only tested 9.4 and 9.4.4)

To Reproduce

  1. yarn create next-app
  2. cd into app
  3. Confirm you have next@~9.4 installed
  4. mv pages/index.js pages/index.tsx
  5. Introduce type error to pages/index.tsx like const x: string = 1234
  6. yarn dev
  7. Load / page and observe that there is no type error printed out.

Expected behavior

There should be type error printed out. This is what it looks like in 9.3.6 when I attempt to load the home page:

[ info ]  bundled successfully, waiting for typecheck results...
[ error ] ERROR in /home/jkim/code/my-app/pages/index.tsx(4,9):
4:9 Type '1234' is not assignable to type 'string'.
    2 |
    3 | export default function Home() {
  > 4 |   const x: string = 1234;
      |         ^
    5 |
    6 |   return (
    7 |     <div className="container">

System information

  • OS: macOS
  • Browser: Firefox
  • Version of Next.js: Tested on 9.3.6, 9.4.0, 9.4.4. Bug found in 9.4.0 and 9.4.4.
  • Version of Node.js: 10.16.3

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 23
  • Comments: 32 (6 by maintainers)

Commits related to this issue

Most upvoted comments

To be extremely clear about why this is so frustrating, let me spell out exactly what’s going on (as it still feels like there’s miscommunication):

The dev experience with only being able to run type-checking on build is quite poor. While builds are slow, that’s not the main pain point. The main pain point is that they don’t re-run on file change. When I introduce a type error into my project, it often takes me multiple type-checking runs to fix the issue. Fixing a Typescript error in one place often introduces a type error somewhere else due to my own carelessness, so I now am forced to run multiple builds (which again, do not re-run on file change, making the experience even slower) in order to make sure all type-checking bugs are caught before push.

Type checking in dev mode is standard behavior in nearly every other framework that offers Typescript support. Create React App works this way, Snowpack works this way, and I’m fairly sure Gatsby works this way. New users coming to Next from these frameworks expect Next to behave the same way. Users that are not aware of this behavior will discover this issue in their CI pipeline, which will fail at some point due to an uncaught error. Most newer developers will simply fix the issue, push the change back, and re-run the CI pipeline repeatedly because they do not understand how builds work. This is not only incredibly annoying, but also yet another thing people need to remember. Instead of just pushing changes to main when you’re done with a feature and have confirmed that it works, you now need to remember to run a (very slow) build locally (many times) so that you don’t waste valuable build minutes on a bug that could’ve been prevented in any other framework.

What makes this even worse is that this is a removed feature. This used to be standard behavior in Next, but it was removed due to performance reasons. Users have complained about this multiple times (see here for an issue comment with over 80 likes). Users would like an option that re-enables this behavior. They’re not asking for it to be the default behavior. They are completely aware of the fact that the core team does not think that this should be the default behavior, and they are fine with that. They are simply asking for this to be enable-able behind a feature flag. Unless there is some technical limitation that I’m not aware of, this should not be hard to implement (for instance, concurrent mode is currently hidden behind a feature flag).

Users are completely aware of the fact that this would slow down build times. Your users are not stupid. They know that adding in Typescript type-checking takes more time and would make fast refresh take more time to do its job. They are simply asking for the option to make that decision for themselves, instead of the core team unilaterally making that decision for them, forcing them to use hacks that do not have the same amount of polish that an official integration would have.

This is how your users are seeing things currently (again, to be extremely clear):

  • User: Could you add back type checking in dev mode?
  • Core team: Type checking was removed due to performance issues. It slowed down reloads by 10x.
  • User: Great, I can deal with slower reloads if it means that my app is type checked during dev mode. However, I understand that not all users want this behavior and that the core team would likely not want to make this the default for all users. Could you re-introduce this removed feature as a feature flag so your users have the option to enable this at their convenience?
  • Core team: Type checking was removed because of performance issues, and we will not introduce it again until someone creates an implementation of it that does not introduce performance issues. If you are able to create an implementation of this that doesn’t slow down rebuilds, then we will re-introduce it.
  • User: Right, I completely understand that type checking slows down rebuilds. I do not care that it slows down rebuilds. I would like the option to re-enable it because the better dev experience of having type-checking on file change outweighs the cost of slower builds for me. Would you be willing to re-introduce this?
  • Core team: Type checking was removed because of performance issues…

Because of this thread and several others, I’m currently going out of my way to explicitly tell people in my network (solo devs and team members alike) to avoid using Next and Vercel. The reason I’m doing this is not because of the poor dev experience here (although that is part of it), but because of the miscommunication and lack of listening to users from the core team here. Reread the bullet points above to understand what this is looking like from your users’ point of view.

The reason why I’m not recommending Next to people currently is not because of any technical issue, but because the core team’s inability to respond effectively to a basic feature request is, frankly, embarrassing. What if this were a more involved bug that was impacting people’s revenue? What if users had an issue with the framework that was causing outages, but when they opened an issue, it felt like they were being met with a wall (as users feel here)?

Please listen to your users. We are not idiots. This is an incredibly basic feature request, but the issues in communication here are a real problem and they should be resolved as well. I have a huge amount of respect for the work you’ve done here and the incredible framework you’ve built that is Next, but at the same time things like this are a very big problem that can impact a project’s long-term success.

This is a major annoyance for me too. Disabling type checks because they’re slow seems ridiculous. If I didn’t want types, I’d be using plain Javascript rather than Typescript.

Disabling type checks means that NextJS can now quickly refresh with buggy code. I would very much prefer it being slower to emit working code.

I don’t really care if Next.JS build times are 10x slower in dev mode, that is my choice whether I enable that or not. Currently there is not even an option for me to do so, which is detrimental to the dev experience. It is incredibly annoying to have to do repeated next build commands to type check even a small app. I would gladly take a 10x slowdown in compilation speed if it meant that I didn’t have to deal with my editor missing an error, deploying to production, having the build work for a few minutes and fail on a Typescript error. It makes me want to drop Next.js in favor of something like CRA.

This comment describes my experience perfectly. The PR that got closed looks like exactly the solution I need, but it’s currently closed.

Very disappointed to see that after two months this has still not been added despite this being a removed feature. Again, the option to be able to run TSC in a blocking way in dev mode (that’s the user experience I want) is much better than the current solution, running next build repeatedly,. It’s not a good dev experience and this really should be revisited.

An option for enabling the feature that was removed would be better than it just being removed.

It has now been four months since my last comment on this, and this experience still has not been improved (despite having a pull request submitted, which was denied). Multiple other comments (some with 70+ likes) have asked for the option to enable this (not supporting this by default, instead allowing users to willingly slow down their dev environment in return for better type checks). This has forced users to come up with unstable workarounds that don’t have the same rich dev experience that official support would bring.

This is a big issue and I’m extremely disappointed that this still hasn’t been resolved. The lackluster dev experience here has pushed me to avoid recommending Next, and by extension Vercel, to teams and other users in my network.

Please do something to fix this. This is a major blocker for me and a large amount of other users and is literally the only thing keeping me from using Next in my projects.

I would like to weigh in on this. Sorry if it seems wordy, that’s just how I write.

I have only recently begun using Next.js for the first time in a personal side project, and one of the reasons I chose to use Next.js is the highly-polished batteries included approach, including its built-in support for TypeScript. For many reasons, I would like to continue using it for this project and possibly for projects in my main job.

That being said, I wasn’t aware that the type checking was disabled and I don’t think that the marketing for Next.js makes that significantly clear. This is significant to me because not having compile time type checking in the project, for me utterly defeats the purpose of TypeScript, and is only marginally better than the informal typing offered by JSDoc.

The types of errors that TypeScript can catch at compile time are responsible for consuming far, far more of my time via manual debugging than the time it takes to run a type-checked compile. I would certainly prefer to have the option to enable a longer-- even 30 second long–type-checked compile mode built into the framework that I can toggle on when I am doing a lot of refactoring, then toggle back off again so I can get back to my normal development speed.

I do have sympathy for the devs who are working on making performant type checking work. I know from working–sometimes for several straight weeks–with every possible combination of Babel plugins, Webpack TS-Loader, Fork-TS-Checker-Webpack-Plugin, TS-Node, incremental compilation flags, etc. etc. …that making TypeScript’s type checker work at all, let alone quickly, is beyond daunting for large projects, especially those that need to run both on the server and in the browser. (My current approach is to to use Webpack with ts-loader and TypeScript’s built-in incremental compilation cache; trying to use the Babel plugin eventually turned into too much of a nightmare and I really can’t recommend it unless its your only choice.)

So, I guess I understand where the delay may be coming from considering how many ways Next.js has to work. But I think that advertising TypeScript support without actually supporting type checking is a bit like advertising that your car has airbags that successfully deploy in the event of an accident but neglecting to mention that they’re actually just thin plastic grocery bags from a grocery store…sorry if that comes across as harsh but it can be a big deal not to have this feature built in. I think I can get by without it for now but that would not be the case for a lot of the projects I had previously considered using Next.js for.

To be clear you can add type checking in development if you want to using custom webpack configuration, that would be the exact same as having the unstable/experimental flag to enable the webpack plugins (which was profiled to increase rebuild times (in development not next build) in the 10 to 20 seconds per file change range and even slower on large projects. Removing the type checking in development was a measure to ensure applications do not see such increases during development. Besides the increased compile time during development there was also a lot of feedback that type checking generally happens in the users editor, e.g. vscode with built-in type checking, or in a separate process using tsc --watch.

module.exports = {
  webpack(config, {isServer}) {
	if(!isServer) {
		const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
		config.plugins.push(new ForkTsCheckerWebpackPlugin())
	}
  	return config
  }
}

November 21 2020 you reached out on twitter, pinging me directly (@timneutkens) here: https://twitter.com/timneutkens/status/1330082043598938113

I replied extensively to your question, you blocked me shortly after I replied without any conversation.


I understand why you want this feature, we just haven’t been able to work on it yet.

This issue was put on the backlog to be worked on in the future by our team (as are 227 other issues), this does not mean we’ll never work on it, it just means we’re not actively working on it right now. An issue staying open for x months simply means that we haven’t been able to work on it extensively because of other feature requests, bugs etc. being solved. This is also why I’ve suggested multiple times that this could be worked on by someone that wants the feature.

We definitely listen to the community and the majority of features introduced into Next.js over the past 2 years have been based on community feedback. I could list them all here if needed.

We’re a small team and have to pick what problem space to focus on. For example right now we’re focusing on ensuring that hot reloading is always fast (coincidentally that relates to this issue as well). We’re adding tracing for every part of Next.js which would later help with introducing this feature in a performant way without hurting DX. These tools weren’t available when we initially added the type checking feature in development, admittedly we missed the slowdown there and wouldn’t have introduced that trade-off if we knew it would slow down compilation significantly. This is one of the main reasons behind the tracing work that we’re doing: ensuring Next.js stays fast as we keep introducing features, fixes, and optimizations. Both in development and production.

This is an incredibly basic feature request

I totally understand that you think this would be as simple as “install a webpack plugin and you’re done” but it’s not that simple. It requires implementing a completely new solutions to run type checking out of band from webpack compilation to ensure it does not block hot reloading which all implementations that currently exist do. Besides running the checker out of band that also means we need an extra overlay that is non-blocking, while the dev overlay currently blocks all interaction on the page. The plugin also significantly increases install size for what it does.

It will likely be slightly simpler to add this custom solution when webpack 5 is rolled out, which we’ve been working on for over a year now to ensure that applications do not break from installing a newer Next.js version.

So overall we’re definitely planning on adding this feature eventually, from our side it’s been blocked on rolling out other work first.

I’m sorry for the short communication in earlier posts. I try to reply to as many notifications as possible to help an issue move forward if we’re not actively working on it, hence my suggestions for an external contribution on this.

I use this workaround in package.json with TypeScript 4 and incremental transpilation (speed is very good)

{
  "scripts": {
    "dev": "next dev",
    "dev:ts": "yarn dev & yarn ts:watch",
    "ts": "tsc --noEmit --incremental",
    "ts:watch": "yarn ts --watch"
  },
}

@samwightt we hear you loud and clear. I truly appreciate the candor and, ultimately, the only way we’re going to make Next.js better is by listening to devs like you who spend the time to tell us how to improve.

We’re in the process of making infrastructure changes that’ll make typechecking during dev time a great experience. Unfortunately, as Tim mentioned, it’s not as easy as adding a quick option just yet. However, I think that ultimately if you’re using TypeScript, you don’t want an option. You don’t want to hack on Webpack configs. You just want it to work®, and provide feedback and guidance while you work.

That’s the magical experience we strive to give and we’ll get there as soon as we can.

Yeah the docs have to be updated, Next.js will only check types at next build as the typescript checker webpack plugin massively slowed down compilation.

Maybe add an opt-in option ?

I’m working on a project in Nextjs for 3 weeks. We built it from scratch.

The first 2 weeks, when the project is still small, we have no problem. But when it’s growing, more and more complicated features come up, sometimes API changes, we decided to enable strict: true in Typescript compilation options. And right after that, I still running the project normally, with some type-check error on Visual Studio Code. I fixed those, then later when I’m trying to deploy to the development server for testing, the build fails due to Typescript errors. That is when I found out that I haven’t fixed all the type errors in the codes, and the errors that VSCode catches only in existing opened files. Again, I fixed some errors and run build, errors. After about 5 times I run the build process, it could’ve succeeded.

Well, today we have a lot of codes to refactor, and we run into issues again. Then I decided to somehow config to catch all the error in development, which I remembered using previous Nextjs version last year, still working. I go through a lot of articles on how to config, and knowing it’s not possible out of the box, we should edit the Webpack configuration itself, like fork-ts-checker-webpack-plugin mentioned above.

And I read a lot of debates above, too. In my opinion, both of you are right: one group thinks it’ll be poor for performance, one group thinks it’ll be better dev experiences, and avoid pushing to CI just to have the build fails. But honestly, I’m more fall into “feature flag group”, sometimes we may have to trade performance for better dev experience. I don’t want to mess up with Webpack configs, let alone installing more packages. And it’s a pain to run builds again and again just for fixing type checks, or open all the files in my editor.

My suggestion is there’s should be a command line flag like --typecheck to next dev. This way, for normal workflows, users don’t use it for performance. But before pushing the codes, they could run with that flag to INCREMENTALLY FIX TYPE ERRORS. You shouldn’t remove it from the start.

You can opt-in to that webpack plugin if you want to as you have access to the webpack configuration, it does not have to be a flag in Next.js. E.g. the PR is wrong nowadays given that we don’t even have that webpack plugin in Next.js anymore as it caused a massive slowdown on builds as well.

Running next build to do type checking is not required. tsc --noEmit (typescript compiler in check mode) is enough to do type checking for example. However, ensure that you’re on the latest version of Next.js given that we run typescript checking as the first thing in the build process now and nothing else is ran before that process finishes, making it the same speed as running tsc --noEmit (we practically do the same just at the start of the build process).

As said we’d be happy to bring this feature back if it runs as a side-process that does not hog resources and can be shown out of band. The webpack plugin does not work well for this case.

I suggest you read my post again and pay attention to the bolded parts because it still feels like there’s miscommunication.

These lines make me feel like you’re again missing the point:

These tools weren’t available when we initially added the type checking feature in development, admittedly we missed the slowdown there and wouldn’t have introduced that trade-off if we knew it would slow down compilation significantly.

It requires implementing a completely new solutions to run type checking out of band from webpack compilation to ensure it does not block hot reloading which all implementations that currently exist do.

Removing the type checking in development was a measure to ensure applications do not see such increases during development. Besides the increased compile time during development there was also a lot of feedback that type checking generally happens in the users editor, e.g. vscode with built-in type checking, or in a separate process using tsc --watch.

Please, please, please pay attention to this:

We don’t care about performance!

10-20s rebuild times are perfectly fine for me so long as I get that type-checking. I can rebuild less-frequently, spend some time sipping my coffee, etc. I will gladly take significantly slower rebuilds if it means I don’t have to spend 20 minutes debugging a Typescript error that got caught in the CI pipeline and not on my local dev machine!

I replied extensively to your question, you blocked me shortly after I replied without any conversation.

Yes, because this is so. incredibly. frustrating. It feels like I’m talking to a brick wall right now. Again: I don’t care about performance!!

I understand and respect the fact that the core team cares significantly about rebuild speeds, and that this is a single feature in the long list of features that y’all are working on. However, I will gladly take a temporary, less-performant implementation of this hidden behind a feature flag over this feature not existing at all.

@samwightt you can read the reasoning here: https://github.com/vercel/next.js/pull/13428#issuecomment-634496718

If you can figure out a performant way to do type checking we’d be happy to merge it. The webpack plugin that CRA uses makes compilation 10x slower when you have typescript files.

I also just wanted to emphasize that I’m not angry or anything, but that I am incredibly frustrated! with this. I have a huge amount of respect for the work you’ve done on Next, and I think it’s an amazing framework. Vercel is a fucking fantastic product too! This is not me trying to shit on the work you’ve done here or the fantastic work the core team has done here.

However, I feel very! frustrated! that it feels like we’re talking in circles here. It feels like after I did my best to spell out what I was seeing as explicitly as I could, that the point was still missed somehow. This is why I can’t recommend Next to devs in my network: because this communicational problem is an issue.

Again, I have a huge amount of respect for you and the rest of the team, I’m just trying to be brutally honest here so y’all are able to do with that information what you will.

It’s been 8 months since my last comment on here, a year since my first comment, and almost a year and a half since the issue was open. Just want to continue to reiterate how much of a bad dev experience this is, especially for newer developers. It’s also been a major reason why teams I’ve worked on haven’t ended up using Next.

We use Vite on my team, and it has this same behavior by default. One of the newer developers, who’s still learning TypeScript (as it’s a beast sometimes), will edit a type and not run a build before pushing. Sometimes those changes will cause a type issue in one of the files not open in VSCode, so they won’t get that error until it hits CI (just like I said in my last comment).

The problem here, and one I didn’t think about, was that they don’t know how to map the error they see to the file and line that it occurs on. Some of the files in our project are really large, and they don’t know how to navigate them as well as people who’ve been working on it for longer. They’ll often fix the change, forget to run a rebuild, and then encounter another problem in CI. So they’ll often ask another developer to help them out with fixing the problem.

Thankfully, Vite has a wonderful plugin for running TypeScript in development with incremental building. The dev experience is very nice and since introducing it, the number of errors in CI has gone down. Next, as far as I know, still doesn’t have an equivalent that integrates nicely with the dev server, which just makes the entire development experience worse.

With Vite or Snowpack or CRA, it either works out of the box or I can install a small package that integrates directly with the dev server. With Next, users are forced to either fuck around with their Webpack config, which goes against the entire reason they chose Next, or deal with awkward CLI workarounds using npm-run-all or something similar. Those integrate with the console, but they don’t integrate with the dev server. It’s easy for the TypeScript errors to be overwritten / just not seen if you have a lot of rebuild messages from Next.

I’ve had a lot of fun working in Next in side projects, but this has been a thorn in my side on every. single. one. It’s something that you think wouldn’t be an issue, but when you’ve worked in a framework like Snowpack, CRA, or Vite, the lack of a good dev experience around this becomes more and more annoying. On most of these projects, I often get so annoyed with having to debug issues in CI that I swap the app over to another framework. This is yet again why I no longer recommend Next to developers.

I understand the team has other priorities right now (the stuff with SWC looks super exciting!), but I just want to reiterate how bad of a dev experience this is currently. This upsets me not because it’s a feature that I want, but because it’s the only feature stopping me from using Next. It’s literally that annoying / bad for me. I really, really hope that something comes through the pipeline soon, cause I would love to have a development / deployment experience with Next where it doesn’t feel like I’m battling against CI.

Seconded, an opt-in option would be very much appreciated. Being forced to run next build repeatedly to debug an error spread throughout the code base is not a very good development experience. It’s cumbersome and very slow. I would love an option to type check on next dev, I’d take a slower reload time any day over repeated builds.

I use this workaround in package.json with TypeScript 4 and incremental transpilation (speed is very good)

{
  "scripts": {
    "dev": "next dev",
    "dev:ts": "yarn dev & yarn ts:watch",
    "ts": "tsc --noEmit --incremental",
    "ts:watch": "yarn ts --watch"
  },
}

Nice solution. I would run both tasks with concurrently or such, otherwise when you exit with ctrl-c the “yarn dev” task remains in the background

I’ve been using this kind of setup without issue.

My config:

"scripts": {
    "dev": "concurrently -n NEXT,TS -c magenta,cyan \"next dev -p 1234\" \"yarn ts --watch\"",
    "ts": "tsc --noEmit --incremental --preserveWatchOutput --pretty"
}

I use this workaround in package.json with TypeScript 4 and incremental transpilation (speed is very good)

{
  "scripts": {
    "dev": "next dev",
    "dev:ts": "yarn dev & yarn ts:watch",
    "ts": "tsc --noEmit --incremental",
    "ts:watch": "yarn ts --watch"
  },
}

Nice solution. I would run both tasks with concurrently or such, otherwise when you exit with ctrl-c the “yarn dev” task remains in the background

Earlier in the thread, @timneutkens said ( https://github.com/vercel/next.js/issues/14997#issuecomment-670364227 ):

If you can figure out a performant way to do type checking we’d be happy to merge it

Given that the Next team is busy, it seems like the community would need to contribute this separately. Has anyone tried looking at what Vite does and applying a similar approach that could be filed as a PR?

Just wanna throw my hat in the ring to advocate for this to be reintroduced as an option. I’m not sure how the feature worked previously, but the thing that the workarounds mentioned in previous comments fail to address are amplified by integrating changes with multiple other developers on the same project.

Having to open two separate shells with different tasks for both next and tsc adds an extra layer that can easily be missed until a deployment is run. Everyone I work with knows to run yarn dev and they’re off to the races. It’s easy to visually grok from the package.json that you start development with yarn dev.

Looking at the package.json, it wouldn’t be immediately obvious that multiple commands need to be run to begin development. This could be mentioned in a README or verbally communicated, but then we leave it up to every dev working on the project to remember both commands, every time.

It’s possible to automate this with something like concurrently, but the output disappears frequently on compile and errors could be missed. The best solution is, like any other next error, for the stack trace to be shown on the webpage where it cant be missed.

I’m currently working on a project with a colleague who lives in another country with a 6 hour time difference. If given the option, I would gladly sacrifice upwards of 30 second rebuild times, if it saves me the entire weekend it’s gonna take for me to inform him his deploy will fail because a prop was not made optional, him updating the code next monday, and me reviewing the PR and finally deploying.

Just want to share some experience:

After getting back to work from holidays and working an a fairly large CRA app with typescript, I’ve come to appreciate the approach that nextjs has taken. Doing small changes and having to wait typescript to compile is quite annoying and I wish more and more that it was faster.

That said, I still find the lack of builtin typescript compilation support for nextjs’ dev command really frustrating (especially since it was a thing, and was removed in a point release). Anyways, running tsc in another terminal isn’t that big of a deal, but I think the docs should at least mention that.

Nextjs is awesome(!) and it makes my life easier. Keep up the great work 😄

I just ran into this. I was super confused when my code worked locally but failed to build in CI. Then I looked in VS Code and sure enough there were errors showing up there too. But the code was running fine locally and next dev wasn’t complaining! I started wondering if somehow I was looking at the wrong file in VS Code or maybe VS Code wasn’t saving my changes. I quit and restarted next dev to see if somehow it was failing to pick up my changes. I was getting really confused. Finally I tried introducing a really egregious error to the file and verified that that broke next dev so I finally realized that next dev was picking up my changes; it just wasn’t type-checking my code! 😱

While technically I knew it was possible to have TypeScript transpile your code without actually compiling / type-checking it, it definitely didn’t occur to me that that would be the default behavior in a mainstream dev tool. Even more surprising that it’s not configurable, though I see people have found a myriad of workarounds. I hope you’re making progress on this one!

Has anyone tried looking at what Vite does and applying a similar approach that could be filed as a PR?

Clarification: Vite does this through a plugin (it has a built-in plugin system largely compatible with Rollup), not by default. Snowpack’s default TS template does this by default, though, so it might be worth exploring. CRA uses Webpack so that might be even better.

Is there any update on this? It’d be really great if we had the option to do this. Create React App already has the ability to do this, I don’t see why Next.js shouldn’t have the same.