Handling Of Tsconfig Modules By The Downstream Toolchain
esbuild
Focuses on providing ultimate build performance, while leaving complex type checking to specialized tools. In modern frontend engineering practices, this separation of responsibilities is a completely reasonable architectural decision.
esbuild
does not fully respect all configurations in the project's tsconfig.json
during the build phase. Only specific tsconfig.json
fields are respected.
During the bundling process, esbuild
's path resolution algorithm will consider the contents of the tsconfig.json
file, where esbuild
will use the tsconfig.json
file closest to the parent directory to modify its behavior.
During the build phase, you can use esbuild
's build api
to explicitly specify the path to the tsconfig.json
file through the tsconfig
field.
During the transform phase, you can use the transform api
to explicitly pass the contents of the tsconfig.json
file through the tsconfigRaw
field.
However, esbuild
currently only respects the following fields in the tsconfig.json
file, and all other fields are ignored.
Decorator
Reference Materials
This option enables the transformation of decorator syntax in typescript
modules. When experimentalDecorators
is enabled, the transformation follows the outdated decorator design that typescript
itself follows.
Note that javascript
is adding a newer decorator design, and when experimentalDecorators
is disabled, typescript
will also adopt this design. This is not currently implemented in esbuild
, so when experimentalDecorators
is disabled, esbuild
currently does not transform decorators.
Class Fields
These options control whether class fields in typescript
files are compiled using define
semantics or assign
semantics:
Define
semantics (default behavior inesbuild
):typescript
class fields behave like regularjavascript
class fields. Field initializers do not trigger setters on the base class. You should adopt this approach when writing all new code in the future.Assign
semantics (requires explicit enabling):esbuild
emulatestypescript
's traditional class field behavior. Field initializers will trigger base class setters. This may be necessary for running legacy code.
The way to disable define
semantics in esbuild
(thus enabling assign
semantics) is the same as in typescript
: set useDefineForClassFields
to false
in the tsconfig.json
file. For compatibility with typescript
, esbuild
also copies typescript
's behavior where if useDefineForClassFields
is not specified, it defaults to false
if the tsconfig.json
contains a target
earlier than ES2022
. However, I recommend explicitly setting useDefineForClassFields
if you need it, rather than relying on the default value from the target
setting. Note that the target
setting in tsconfig.json
is only used by esbuild
to determine the default value for useDefineForClassFields
. It does not affect esbuild
's own target
setting, despite having the same name.
Path Resolution
These options affect how esbuild
resolves import/require
paths to files on the filesystem. You can use them to define package aliases and otherwise rewrite import paths.
Note that using esbuild
for import path transformation requires enabling bundling, as esbuild
's path resolution process only occurs during bundling. Also note that esbuild
has a native alias feature that you might want to use instead.
JSX Transformation
These options affect how esbuild
transforms jsx
syntax into javascript
. They are equivalent to esbuild
's native options: jsx
, jsxFactory
, jsxFragment
, and jsxImportSource
.
Strict Mode
If any of these options are enabled, esbuild
will consider all code in all TypeScript
files to be in strict mode and will add "use strict"
before the generated code, unless the output format is set to esm
(because all esm
modules are in strict mode by default).
Import Side Effect Control
By default, the typescript
compiler removes unused imports when converting typescript
to javascript
. This means that if a module only depends on types from other modules (type imports
), imports that unexpectedly become type-only imports won't cause errors at runtime. esbuild
also implements this behavior.
These options allow you to disable this behavior and preserve unused dependency imports, which can be useful if the imported module has side effects. You should use verbatimModuleSyntax
for this, as it replaces the older importsNotUsedAsValues
and preserveValueImports
settings (which are now deprecated in TypeScript
).
Configure Extensions
Reference Materials
This option allows you to split your tsconfig.json
file into multiple files. This value can be either a single inheritance string or an array for multiple inheritance (a new feature in typescript
5.0+).
Others
All other tsconfig.json
fields (i.e., those not in the above list) will be ignored.
Summary
- Focus on Transpilation, Not Type Checking:
esbuild
focuses on supporting configurations that affect code transpilation and module resolution, rather than type system configurations. This aligns with its positioning as a high-performance bundling tool. - Performance Trade-offs: By only focusing on a few necessary fields,
esbuild
maintains its excellent performance advantages. Full support fortypescript
configuration would bring additional complexity and performance overhead. - Pragmatic Approach: The supported fields all directly affect the behavior of generated code or module resolution, which are the most core aspects of the bundling process.
- Overlap with Native Features: Some
tsconfig
fields (such asjsx
-related configurations) overlap withesbuild
's own configuration options, providing flexibility for developers. - Incomplete Support for New Standards: Notably,
esbuild
has not yet implemented the new decorator design, which may affect projects using the latest decorator syntax.
Practical Understanding:
When using esbuild
to bundle a ts
project:
- You can use
tsc
for type checking, lettingesbuild
handle transpilation and bundling, leveraging their respective strengths. - Be aware of decorator compatibility issues, especially for projects using new decorator syntax.
- In the
CI
process, separate type checking and building into independent steps to fully utilizeesbuild
's speed advantages.