Patch typescript to support custom transformers in tsconfig.json
npm install ts-patch

!Build Status
Patch typescript to allow custom transformers (plugins) during build.
Plugins are specified in tsconfig.json, or provided programmatically in CompilerOptions.
_Migrating from ttypescript is easy! See: Method 1: Live Compiler_
* Patch typescript installation via on-the-fly, in-memory patching _or_ as a persistent patch
* Can patch individual libraries (see ts-patch /?)
* Hook build process by transforming the Program (see: Transforming Program)
* Add, remove, or modify diagnostics (see: Altering Diagnostics)
* Fully compatible with legacy ttypescript projects
* (new) Experimental support for ES Module based transformers
* ts-patch
* Features
* Table of Contents
* Installation
* Usage
* Method 1: Live Compiler
* Method 2: Persistent Patch
* Configuration
* Plugin Options
* Writing Transformers
* Source Transformers
* Source Transformer Entry Point
* Source Transformer Example
* Altering Diagnostics
* Note
* Program Transformers
* Program Transformer Entry Point
* Configuring Program Transformers
* Program Transformer Example
* Plugin Package Configuration
* Example
* Resources
* Recommended Reading
* Recommended Tools
* Discussion
* Advanced Options
* Maintainers
* Help Wanted
* License
1. Install package
``sh`
The live compiler patches on-the-fly, each time it is run.
Via commandline: Simply use tspc (instead of tsc)
With tools such as ts-node, webpack, ts-jest, etc: specify the compiler as ts-patch/compiler
Persistent patch modifies the typescript installation within the node_modules path. It requires additional configuration
to remain persisted, but it carries less load time and complexity compared to the live compiler.
1. Install the patch
`shell`For advanced options, see: ts-patch /?
ts-patch install
2. Add prepare script (keeps patch persisted after npm install)
package.json`
jsonc`
{
/ ... /
"scripts": {
"prepare": "ts-patch install -s"
}
}
tsconfig.json: Add transformers to compilerOptions in plugins array.
Examples
`jsonc
{
"compilerOptions": {
"plugins": [
// Source Transformers
{ "transform": "transformer-module" },
{ "transform": "transformer2", "extraOption": 123 },
{ "transform": "trans-with-mapping", "resolvePathAliases": true },
{ "transform": "esm-transformer", "isEsm": true },
// Program Transformer
{ "transform": "transformer-module5", "transformProgram": true }
]
}
}
`
| Option | Type | Description |
|--------------------|---------|:--------------------------------------------------------------------------------------------------------------|
| transform | string | Module name or path to transformer _(.ts or .js)_ |
| after | boolean | Apply transformer after stock TS transformers |
| afterDeclarations | boolean | Apply transformer to declaration (*.d.ts) files |
| transformProgram | boolean | Transform Program during ts.createProgram() _(see: Program Transformers)_ |default
| isEsm | boolean | Transformer is ES Module (_note: experimental_ — requires esm) |
| resolvePathAliases | boolean | Resolve path aliases in transformer (requires tsconfig-paths) |
| type | string | See: Source Transformer Entry Point (default: 'program') |
| import | string | Name of exported transformer function _(defaults to export)_ |
| tsConfig | string | tsconfig.json file _for transformer_ (allows specifying compileOptions, path mapping support, etc) |
| _..._ | | Provide your own custom options, which will be passed to the transformer |
_Note: Required options are bold_
For an overview of the typescript compiler (such as what a SourceFile and Program is) see: Typescript Compiler Notes.
Source Transformers will transform the AST of SourceFiles during compilation, allowing you to alter the output of the JS or declarations files.
`ts`
(program: ts.Program, config: PluginConfig, extras: TransformerExtras) => ts.TransformerFactory
PluginConfig: Type Declaration
TransformerExtras: Type Declaration
ts.TransformerFactory: (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile
_Note: Additional legacy signatures are supported, but it is not recommended to develop a new transformer using them._
Transformers can be written in JS or TS.
`ts
import type * as ts from 'typescript';
import type { TransformerExtras, PluginConfig } from 'ts-patch';
/* Changes string literal 'before' to 'after' /
export default function (program: ts.Program, pluginConfig: PluginConfig, { ts: tsInstance }: TransformerExtras) {
return (ctx: ts.TransformationContext) => {
const { factory } = ctx;
return (sourceFile: ts.SourceFile) => {
function visit(node: ts.Node): ts.Node {
if (tsInstance.isStringLiteral(node) && node.text === 'before') {
return factory.createStringLiteral('after');
}
return tsInstance.visitEachChild(node, visit, ctx);
}
return tsInstance.visitNode(sourceFile, visit);
};
};
}
`
Live Examples:
{ transform: "typescript-transform-paths" }
{ transform: "typescript-is/lib/transform-inline/transformer" }
{ transform: "typia/lib/transform" } (💻playground)
{ transform: "@nestia/core/lib/transform" }
Diagnostics can be altered in a Source Transformer.
To alter diagnostics you can use the following, provided from the TransformerExtras parameter:
| property | description |
|--------------------|-----------------------------------------------------|
| diagnostics | Reference to Diagnostic array | Diagnostic
| addDiagnostic() | Safely add to diagnostics array |Diagnostic
| removeDiagnostic() | Safely remove from diagnostics array |
_This alters diagnostics during _emit only_. If you want to alter diagnostics in your IDE as well, you'll need to create a LanguageService plugin to accompany your source transformer_
Sometimes you want to do more than just transform source code. For example you may want to:
- TypeCheck code after it's been transformed
- Generate code and add it to the program
- Add or remove emit files during transformation
For this, we've introduced what we call a Program Transformer. The transform action takes place during ts.createProgram, and allowsProgram
re-creating the instance that typescript uses.
`ts`
(program: ts.Program, host: ts.CompilerHost | undefined, options: PluginConfig, extras: ProgramTransformerExtras) => ts.Program
ProgramTransformerExtras >>> Type Declaration
To configure a Program Transformer, supply "transformProgram": true in the config transformer entry.
_Note: The before, after, and afterDeclarations options do not apply to a Program Transformer and will be ignored_
TypeScript
/**
* Add a file to Program
*/
import * as path from 'path';
import type * as ts from 'typescript';
import type { ProgramTransformerExtras, PluginConfig } from 'ts-patch';export const newFile = path.resolve(__dirname, 'added-file.ts');
export default function (
program: ts.Program,
host: ts.CompilerHost | undefined,
options: PluginConfig,
{ ts: tsInstance }: ProgramTransformerExtras
) {
return tsInstance.createProgram(
/ rootNames / program.getRootFileNames().concat([ newFile ]),
program.getCompilerOptions(),
host,
/ oldProgram / program
);
}
`Note: For a more complete example, see Transforming Program with additional AST transformations
Live Examples:
{ transform: "@typescript-virtual-barrel/compiler-plugin", transformProgram: true }{ transform: "ts-overrides-plugin", transformProgram: true }Plugin Package Configuration
The plugin package configuration allows you to specify custom options for your TypeScript plugin.
This configuration is defined in the
package.json of your plugin under the tsp property.An example use case is enabling
parseAllJsDoc if you require full JSDoc parsing in tsc for your transformer in TS v5.3+. (see: 5.3 JSDoc parsing changes)For all available options, see the
PluginPackageConfig type in plugin-types.ts$3
`jsonc
{
"name": "your-plugin-name",
"version": "1.0.0",
"tsp": {
"tscOptions": {
"parseAllJsDoc": true
}
}
}
`Resources
$3
- How-To: Advice for working with the TS Compiler API
- How-To: TypeScript Transformer Handbook
- Article: How to Write a TypeScript Transform (Plugin)
- Article: Creating a TypeScript Transformer
$3
| Tool | Type | Description |
|----------------------------------------------------------------------|-------------|---------------------------------------------------------------------------------------------|
| TS AST Viewer | Web App | Allows you to see the
Node structure and other TS properties of your source code. |
| ts-expose-internals | NPM Package | Exposes internal types and methods of the TS compiler API |$3
-
#compiler-internals-and-api on TypeScript Discord Server
- TSP Discussions BoardAdvanced Options
(env)
TSP_SKIP_CACHESkips patch cache when patching via cli or live compiler.
(env)
TSP_COMPILER_TS_PATHSpecify typescript library path to use for
ts-patch/compiler (defaults to require.resolve('typescript'))(env)
TSP_CACHE_DIROverride patch cache directory
(cli)
ts-patch clear-cacheCleans patch cache & lockfiles
Maintainers

Ron S.
Help Wanted
If you're interested in helping and are knowledgeable with the TS compiler codebase, feel free to reach out!
License
This project is licensed under the MIT License, as described in
LICENSE.md`