Search code examples
node.jstypescriptexpresstsconfig

Why does `allowJS` cause an unwanted `src` subdirectory in my compiled output?


I'm converting a legacy node/express codebase to TypeScript, following the Microsoft TypeScript starter as a starting reference.

In this reference output is compiled to dist, however when enabling allowJS in tsconfig.json, the output is emitted to dist/src - why is that?

Here is my tsconfig.json

{
"compilerOptions": {
  "module": "commonjs",
  "target": "es6",
  "noImplicitAny": false,
  "moduleResolution": "node",
  "sourceMap": true,
  "rootDir" : "./",
  "outDir": "dist",
  "baseUrl": ".",
  "allowJs": true,
  "paths": {
    "*": [
      "node_modules/*",
      "src/types/*"
    ]
  }
},
"include": [
  "src/**/*"
]

}

  • I tried changing rootDir to ./src but it gives an error saying 'node_modules/someModule' is not in the src root.
  • I tried moving tsconfig.json to src, according to a GitHub issue I saw, but no output was generated.

AllowJS

The output was mapping correctly under /dist until allowJS flag was turned on in tsconfig.json, after which output appeared in /dist/src


Solution

  • There are two things going on here:

    • Typescript relies on rootDir to decide the directory structure of the output (see this comment from Typescript's bossman).
    • Only code within the rootDir can be compiled/emitted by tsc.
    • If you don't set rootDir explicitly, it defaults to ./ (relative to tsconfig)... unless you've included something outside of ./ that needs to be compiled/emitted by tsc, in which case it forces rootDir to automatically get set to the directory that contains all the source.
    • The allowJS setting tells tsc to treat .js code as source and to also emit it to the outDir.

    I suspect that when you enabled allowJS, there was .js code outside of src that tsc now had to emit to outDir, and so it automatically moved rootDir one level up. Since src is now a subdir of the rootDir, this gets mirrored within outDir.

    See this answer for a solution that enables you to have src remain a rootDir and also include code from outside of it.