Troubleshooting ts_project failures
ts_project is a thin wrapper around the
tsc compiler from TypeScript. Any code that works with
tsc should work with
ts_project with a few caveats:
ts_projectalways produces some output files, or else Bazel would never run it. Therefore you shouldn't use it with TypeScript's
noEmitoption. If you only want to test that the code typechecks, use
tscdirectly. See examples/typecheck_only
- Your tsconfig settings for
declarationDirare ignored. Bazel requires that the
declarationDir) be set beneath
- Bazel expects that each output is produced by a single rule.
Thus if you have two
ts_projectrules with overlapping sources (the same
.tsfile appears in more than one) then you get an error about conflicting
.jsoutput files if you try to build both together. Worse, if you build them separately then the output directory will contain whichever one you happened to build most recently. This is highly discouraged.
You can often create a minimal repro of your problem outside of Bazel. This is a good way to bisect whether your issue is purely with TypeScript, or there's something Bazel-specific going on.
The basic methodology for diagnosing problems is:
- Gather information from Bazel about how
tscis spawned, like with
bazel aquery //path/to:my_ts_project.
- Reason about whether Bazel is providing all the inputs to
tscthat you expect it to need. If not, the problem is with the dependencies.
- Reason about whether Bazel has predicted the right outputs.
- Gather information from TypeScript, typically by adding flags to the
argsattribute of the failing
ts_project, as described below. Be prepared to deal with a large volume of data, like by writing the output to a file and using tools like an editor or unix utilities to analyze it.
- Reason about whether TypeScript is looking for a file in the wrong place, or writing a file to the wrong place.
Which files should be emitted
TypeScript emits for each file in the "Program".
--listFiles is a
tsc flag to show what is in the program, and
--listEmittedFiles shows what was written.
Upgrading to TypeScript 4.2 or greater can be helpful, because error messages were improved, and new flags were added.
error TS6059: File '/private/var/tmp/_bazel_alex.eagle/efa8e81f99c35c1227ef40a83cd29a26/execroot/examples_jest/ts/test/index.test.ts' is not under 'rootDir' '/private/var/tmp/_bazel_alex.eagle/efa8e81f99c35c1227ef40a83cd29a26/execroot/examples_jest/ts/src'. 'rootDir' is expected to contain all source files. Target //ts/src:src failed to build
error TS6059: File '/private/var/tmp/_bazel_alex.eagle/efa8e81f99c35c1227ef40a83cd29a26/execroot/examples_jest/ts/test/index.test.ts' is not under 'rootDir' '/private/var/tmp/_bazel_alex.eagle/efa8e81f99c35c1227ef40a83cd29a26/execroot/examples_jest/ts/src'. 'rootDir' is expected to contain all source files. The file is in the program because: Matched by include pattern '**/*' in 'tsconfig.json'
--explainFiles flag in TS 4.2 also gives information about why a given file was added to the program.
Module not resolved
--traceResolution flag to
tsc to understand where TypeScript looked for the file.
Verify that there is actually a
.d.ts file for TypeScript to resolve. Check that the dependency library has the
declarations = True flag set, and that the
.d.ts files appear where you expect them under
error TS5033: Could not write file 'bazel-out/x64_windows-fastbuild/bin/setup_script.js': EPERM: operation not permitted, open 'bazel-out/x64_windows-fastbuild/bin/setup_script.js'.
This likely means two different Bazel targets tried to write the same output file. Use
--listFiles to ask
tsc to show what files are in the program. Try
--explainFiles (see above) to see how they got there.
You may find that the program contained a
.ts file rather than the corresponding
Also see https://github.com/microsoft/TypeScript/issues/22208 - it's possible that TypeScript is resolving a
.ts input where it should have used a
.d.ts from another compilation.