When running npm run dev
with Next JS app router, I'm also starting a dedicated tsc --watch
which is running concurrently.
In short I'm doing this to get "live updates" of errors in file b
, which I don't have open in my IDE, when changing something in file a
which effects file b
.
The long story with many arguments for & against this approach can be found in this discussion in the Next JS repo, where I also got the initial idea for this setup.
This has been working just fine with the old page router but it results in the following errors in an app router application:
[TS] error TS6053: File '/path/to/repo/.next/types/app/api/trpc/[trpc]/route.ts' not found.
[TS] The file is in the program because:
[TS] Matched by include pattern '.next/types/**/*.ts' in '/path/to/repo/tsconfig.json'
[TS]
[TS] tsconfig.json:23:96
[TS] 23 "include": [".eslintrc.cjs", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs", ".next/types/**/*.ts"],
[TS] ~~~~~~~~~~~~~~~~~~~~~
[TS] File is matched by include pattern specified here.
[TS]
[TS] error TS6053: File '/path/to/repo/.next/types/app/layout.ts' not found.
[TS] The file is in the program because:
[TS] Matched by include pattern '.next/types/**/*.ts' in '/path/to/repo/tsconfig.json'
[TS]
[TS] tsconfig.json:23:96
[TS] 23 "include": [".eslintrc.cjs", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs", ".next/types/**/*.ts"],
[TS] ~~~~~~~~~~~~~~~~~~~~~
[TS] File is matched by include pattern specified here.
[TS]
[TS] error TS6053: File '/path/to/repo/.next/types/app/page.ts' not found.
[TS] The file is in the program because:
[TS] Matched by include pattern '.next/types/**/*.ts' in '/path/to/repo/tsconfig.json'
[TS]
[TS] tsconfig.json:23:96
[TS] 23 "include": [".eslintrc.cjs", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs", ".next/types/**/*.ts"],
[TS] ~~~~~~~~~~~~~~~~~~~~~
[TS] File is matched by include pattern specified here.
The app is running just fine, so this doesn't seem to be a real issue.
The folder .next/types/**/*.ts
is in my includes
in the tsconfig.json
:
"include": [".eslintrc.cjs", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs", ".next/types/**/*.ts"],
When simply removing .next/types/**/*.ts
from the config, the errors are gone and everything seems to be working as expected, however, this is re-added automatically, every time I start the dev server, so I'd suspect that it really should be there 🤷♂️
FYI, I've bootstrapped my app using create T3 app which is where api/trpc/[trpc]/route.ts
is "coming from".
Here's my concrete setup, showing how I'm running tsc
concurrently:
"scripts": {
"dev": "concurrently -n NEXT,TS -c grey,green \"next dev\" \"npm run ts:watch\"",
"ts": "tsc --noEmit --incremental --preserveWatchOutput --pretty",
"ts:watch": "npm run ts -- --watch"
},
The concurrently
part is provided from here.
ATM I have removed this concurrent tsc --watch
as the errors shown above are making so much noise that I don't see real errors anymore anyhow but I'm really missing it.
I'd really appreciate some help on how to get my tsc --watch
back without seeing those errors.
This comment in the Next JS GitHub discussion made it clear to me, why my TSC watch is showing those errors in the first place:
There's a race condition as Next is starting to rebuild files within .next/types
when it rebuilds pages (e.g. on page request during dev etc.). However TSC watch is recompiling on file change, which (usually?) happens before page request/next rebuild, so TSC watch is simply compiling "too early" here.
I think I found a solution which works for me:
tsconfig.watch.json
with the following content:
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", ".next/types/**/*.ts"]
}
ts:watch
script: npm run ts -- --watch --project tsconfig.watch.json
This way I don't see any errors from files within .next/types
in my TSC watch but would still see them in the IDE or on build
, which both still use the original tsconfig.json
which includes that folder.
I'm not 100% sure if there are situations where I could be missing important errors now in my watcher at dev time, but ATM this is looking fine for me.