What are the correct typescript compiler (tsc) options to set in order to separate main from test compilation?

吃可爱长大的小学妹 提交于 2021-01-27 12:34:42

问题


NB: A public git repo for this question is at https://github.com/matthewadams/ts-test if you want to have a look at the full project.

I'm trying to separate main source compilation from test source compilation in my project. Here's the source directory structure:

src
  main
    ...typescript source files and possibly child directories with sources
  test
    unit
      ...unit test sources
    integration
      ...integration test sources

My goal is to compile only main sources into lib/main, and only test sources into lib/test.

I'm trying to put all compiler options that should be common to both main & test compilations in tsconfig.json, then use command-line args to tsc to provide the options that are specific to each compilation. Here's my current tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "alwaysStrict": true,
    "diagnostics": true,
    "disableSizeLimit": true,
    "esModuleInterop": true,
    "extendedDiagnostics": true,
    "forceConsistentCasingInFileNames": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "listEmittedFiles": true,
    "listFiles": true,
    "module": "commonjs",
    "pretty": true,
    "target": "es2015"
  }
}

A snippet from package.json scripts section is the following (I reject Gulp, Grunt & the like on the grounds of complexity, knowingly sacrificing portability):

  "scripts": {
    "transpile-main": "rm -rf lib/main && tsc --outDir lib/main --rootDir src/main -d --declarationDir lib/main",
    "transpile-test": "rm -rf lib/test && tsc --outDir lib/test --rootDir src/test --typeRoots lib/main",
    ...other scripts here...
  }

I can compile main sources without an issue, and they appear in lib/main correctly. However, when I compile test sources, I get the following error:

$ npm run transpile-test

> @matthewadams/ts-test@0.1.0-pre.0 transpile-test /Users/matthewadams/dev/me/ts-test
> rm -rf lib/test && tsc --outDir lib/test --rootDir src/test --typeRoots src/main

error TS6059: File '/Users/matthewadams/dev/me/ts-test/src/main/Nameable.ts' is not under 'rootDir' 'src/test'. 'rootDir' is expected to contain all source files.

error TS6059: File '/Users/matthewadams/dev/me/ts-test/src/main/Person.ts' is not under 'rootDir' 'src/test'. 'rootDir' is expected to contain all source files.

error TS6059: File '/Users/matthewadams/dev/me/ts-test/src/main/PersonImpl.ts' is not under 'rootDir' 'src/test'. 'rootDir' is expected to contain all source files.

The thing that's confusing me is the message 'rootDir' is expected to contain all source files. I'm trying to compile test sources against what's in lib/main. I don't want all sources under one directory.

What is the correct combination of tsconfig.json options & tsc cli options to achieve my goal of separate main & test compilations?


回答1:


Error: 'rootDir' is expected to contain all source files.

rootDir is expected to be the root of all source/input files. TS compiler proceeds like this:

collect all input files ("files" / "include" / "exclude" / imports) 
  --> for each included input file
    --> chop off the "rootDir" from the input 
    --> prepend the "outDir"

The src/test files import from src/main, so currently rootDir can only be set to src or above.

Solution: Project References (TS 3.0+)

Project references can solve all of the issues you described:

  • rootDir will be set to src/main or src/test respectively
  • src folder does not appear as part of the lib output
  • src/main cannot import src/test (only vice versa should be possible)
Resulting project structure:
|   tsconfig-base.json            // other config options go here
|   tsconfig.json                 // solution config containing references
|   
+---lib                           // output folder
|   +---main
|   |       mod.d.ts
|   |       mod.js
|   |       tsconfig.tsbuildinfo
|   |       
|   \---test
|           mod-test.js     
\---src
    +---main                      // referenced sub-project main 
    |       mod.ts
    |       tsconfig.json
    |       
    \---test                      // referenced sub-project test 
            mod-test.ts
            tsconfig.json
./tsconfig-base.json:
{
  "compilerOptions": {
    // just some sample values, set your own as needed
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    // other compiler options
  }
}
./tsconfig.json:
{
  "files": [],
  "references": [
    {
      "path": "./src/main"
    },
    {
      "path": "./src/test"
    }
  ]
}
./src/main/mod.ts:
export const foo = "foo";
./src/main/tsconfig.json:
{
  "extends": "../../tsconfig-base.json",
  "compilerOptions": {
    "outDir": "../../lib/main",
    "composite": true // flag to signal referenced project      
  }
}
./src/test/mod-test.ts:
import { foo } from "../main/mod";

// use your test framework here
export function testMod() {
  if (foo !== "foo") throw new Error("foo expected.");
}

testMod()
./src/test/tsconfig.json:
{
  "extends": "../../tsconfig-base.json",
  "compilerOptions": {
    "outDir": "../../lib/test"
  },
  "references": [
    {
      "path": "../main" // test project depends on main
    }
  ]
}
You can build and clean the project with following scripts:
"scripts": {
    "build": "tsc -b -v",
    "clean": "tsc -b --clean"
},

Further links

  • TypeScript Project References Demo


来源:https://stackoverflow.com/questions/57257910/what-are-the-correct-typescript-compiler-tsc-options-to-set-in-order-to-separa

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!