Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript `tsc` not picking up tsconfig.json inside a subdirectory?

Tags:

typescript

I have the following directory structure:

.
├── tsconfig.json ("module": "CommonJS")
└── foo/
    ├── node-file.ts
    └── bar/
        ├── browser-file.ts
        └── tsconfig.json ("module": "esnext")

The root tsconfig.json has module set to CommonJS because I want most of my files to compile for Node. But inside bar, I want the files to compile to JavaScript Modules, so I've set module to esnext.

Now when I run tsc from the root, I expect node-file.ts to compile to CommonJS module and browser-file.ts to compile to a JavaScript Module. But that's not what I'm getting. It seems that tsc is completely ignoring foo/bar/tsconfig.json and is only picking up the root tsconfig.json.

(I also use tsc --watch while developing, so I'm trying to avoid having to run two different tsc processes to compile the two different targets. It feels to me that running a single tsc with nested tsconfig.json files should give me the desired results.)

Anyone know what it is that I'm doing wrong?

like image 434
M.K. Safi Avatar asked Oct 31 '20 22:10

M.K. Safi


People also ask

Can you have multiple Tsconfig json files?

You could use multiple tsconfig files to solve some of those problems, but new ones would appear: There's no built-in up-to-date checking, so you end up always running tsc twice.

What is the use of Tsconfig json file in TypeScript?

The tsconfig.json file specifies the root files and the compiler options required to compile the project. JavaScript projects can use a jsconfig.json file instead, which acts almost the same but has some JavaScript-related compiler flags enabled by default.


1 Answers

TypeScript only uses one tsconfig.json and doesn't automatically use subdirectories' tsconfig.json for the files there. However, you can use project references for this.

Create a directory structure like this:

.
├── tsconfig.json
├── tsconfig.settings.json (optional)
└── foo/
    ├── node-file.ts
    ├── tsconfig.json ("module": "commonjs")
    └── bar/
        ├── browser-file.ts
        └── tsconfig.json ("module": "esnext")

tsconfig.json

{
  "files": [],
  "references": [
    {"path": "./foo"},
    {"path": "./foo/bar"}
  ]
}

This is the root tsconfig.json. When you run tsc --build (see below) in the root directory, TypeScript will build the referenced projects ./foo/tsconfig.json and ./foo/bar/tsconfig.json.

The "files": [] is to stop accidental tscs without --build from attempting to compile everything in the root directory, which will error but create multiple .js files in possibly the incorrect places.

tsconfig.settings.json (optional)

{
  "compilerOptions": {
    "strict": true,
    "noImplicitReturns": true
  }
}

You can put configuration common to foo and foo/bar and extend this configuration with extends to reduce duplication. Note that all relative paths in here will be resolved relative to tsconfig.settings.json when extended, so something like "outDir": "dist" may not work as expected.

foo/tsconfig.json

{
  "extends": "../tsconfig.settings.json",
  "exclude": ["bar/**/*.ts"],
  "compilerOptions": {
    "module": "commonjs"
  }
}

This is the configuration for the CommonJS files. It also extends the common config and excludes the files in foo/bar.

foo/bar/tsconfig.json

{
  "extends": "../../tsconfig.settings.json",
  "compilerOptions": {
    "module": "esnext"
  }
}

This is pretty similar to foo's configuration.


Building

To compile foo and foo/bar at the same time, use build mode from the root directory:

tsc --build # or tsc -b
# Watch mode:
tsc --build --watch # or tsc -b -w

From the handbook:

A long-awaited feature is smart incremental builds for TypeScript projects. In 3.0 you can use the --build flag with tsc. This is effectively a new entry point for tsc that behaves more like a build orchestrator than a simple compiler.

Running tsc --build (tsc -b for short) will do the following:

  • Find all referenced projects
  • Detect if they are up-to-date
  • Build out-of-date projects in the correct order

You can provide tsc -b with multiple config file paths (e.g. tsc -b src test). Just like tsc -p, specifying the config file name itself is unnecessary if it’s named tsconfig.json.

You can also compile individual projects:

tsc -b foo # or cd foo && tsc
tsc -b foo/bar # or cd foo/bar && tsc

Note that are some build-only flags and you cannot override compiler options with command-line arguments.

like image 112
cherryblossom Avatar answered Sep 25 '22 03:09

cherryblossom