Skip to content

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

experimentalDecorators

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 in esbuild): typescript class fields behave like regular javascript 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 emulates typescript'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

Reference Materials

baseUrl

paths

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

Reference Materials

alwaysStrict

strict

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

extends

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 for typescript 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 as jsx-related configurations) overlap with esbuild'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:

  1. You can use tsc for type checking, letting esbuild handle transpilation and bundling, leveraging their respective strengths.
  2. Be aware of decorator compatibility issues, especially for projects using new decorator syntax.
  3. In the CI process, separate type checking and building into independent steps to fully utilize esbuild's speed advantages.

@rollup/plugin-typescript

Contributors

Changelog

Discuss

Released under the CC BY-SA 4.0 License. (dbcbf17)