问题
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:
rootDirwill be set tosrc/mainorsrc/testrespectivelysrcfolder does not appear as part of theliboutputsrc/maincannot importsrc/test(only vice versa should be possible)
| 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