The TypeScript compiler
Type-checking can be slow, and is really only possible with TypeScript, not with alternative tools, because the type system is so rich that writing a correct checker is a massive undertaking.
Transpilation is mostly "erase the type syntax" and can be done well by a variety of tools.
tsc is regarded as the slowest option for transpilation, so it makes sense to divide the work between two tools.
ts_project supports this with the following design goals:
- The user should only need a single BUILD.bazel declaration of "this is my TypeScript code and its dependencies".
- Most developers have a working TypeScript Language Service in their editor, so they got type hinting before they ran the build tool.
- Development activities which rely only on runtime code, like running tests or manually verifying behavior in a devserver, should not need to wait on type-checking.
- Type-checking still needs to be verified before checking in the code, but only needs to be as fast as a typical test.
Read more: https://blog.aspect.dev/typescript-speedup
transpiler attribute of
None means that
tsc should do transpiling along with type-checking, as this is the simplest configuration without additional dependencies. However as noted above, it's also the slowest.
transpiler attribute accepts a rule or macro with this signature:
name, srcs, **kwargs
**kwargs attribute propagates the tags, visibility, and testonly attributes from
If you need to pass additional attributes to the transpiler rule such as
out_dir, you can use a
to bind those arguments at the "make site", then pass that partial to this attribute where it will be called with the remaining arguments.
The transpiler rule or macro is responsible for predicting and declaring outputs.
If you want to pre-declare the outputs (so that they can be addressed by a Bazel label, like
then you should use a macro which calculates the predicted outputs and supplies them to a
on the rule.
See the examples/transpiler directory for a simple example using Babel, or
for a more complete example that also shows usage of SWC.
When a custom transpiler is used, then the
ts_project macro expands to these targets:
[name]- the default target which can be included in the
depsof downstream rules. Note that it will successfully build even if there are typecheck failures because invoking
tscis not needed to produce the default outputs. This is considered a feature, as it allows you to have a faster development mode where type-checking is not on the critical path.
[name]_typecheck- provides typings (
.d.tsfiles) as the default output. Building this target always causes the typechecker to run.
build_testtarget which simply depends on the
[name]_typechecktarget. This ensures that typechecking will be run under
[name]_typings- internal target which runs the binary from the
- Any additional target(s) the custom transpiler rule/macro produces. (For example, ome rules produce one target per TypeScript input file.)