TypeScript tsc type check with references in monorepos

Viewed 801

I'm using Yarn Workspaces, and I want a cli-command to check the types of my source ts files located at packages/*.

Originally I build my project by using webpack (with esbuild, which does not check types) and check types with tsc --noEmit standalone. And they worked together very well.

After switching to Yarn Workspaces I splited my whole project into a couple of small packages.

The whole project is like this:

packages/
  foo/
    index.ts          // import bar from 'bar'; console.log(bar);
    package.json      // { "name": "foo" }
    tsconfig.json     // { "references": [ { "path": "../bar" } ] }
  bar/
    index.ts          // export default "hello world";
    package.json      // { "name": "bar" }
    tsconfig.json     // { "compilerOptions": { "composite": true } }
package.json          // { "workspaces": [ "packages/*" ] }

And then I found tsc failed to run. When I try tsc --noEmit -p packages/foobar it fails with a bunch of errors like:

Output file '/packages/foobar/index.d.ts' has not been built from source file '/packages/foobar/index.ts'.

However webpack works very well.

After surfing the internet, the official document tould me that those two feature could only be used in build mode. But when I tried tsc --noEmit -b packages/foobar it also fails due to conflicts between --noEmit flag and build mode. Moreover, if I removed --noEmit flag, tsc will try to generate a bunch of .js files for me but I don't want them to be generated.

I just want a cli-command to check types without outputing any extra files like what my IDE does. How can I run tsc correctly? or is there any alternatives to this?

2 Answers

Try adding typescript as the dependency into package.json of the package you want to get checked.

(edit): also doesn't look like tsc --noemit works with project references...

Just ran into the same problem, and "solved" by using TS Project References and I added following to my tsconfig.json

"compilerOptions": {
  ...
  "emitDeclarationsOnly": true,
  ...
}

This tells the Typescript compiler to not transpile any of the TS to JS but only emit the .d.ts declarations files.

Then in my package.json :

scripts: {
   "lint": "tsc -b"
}
"

This will build any TS project references and the project you're running tsc in. Though since we have 'emitDeclarationOnly' turned on, it'll only build declaration files for this proj.

Related