What is ts-patch?
ts-patch is a tool that allows you to patch the TypeScript compiler (tsc) to enable custom transformers and other advanced features. It is particularly useful for developers who need to extend the capabilities of TypeScript beyond what is natively supported.
What are ts-patch's main functionalities?
Custom Transformers
This feature allows you to apply custom transformers to the TypeScript compiler. By patching the compiler, you can specify custom transformers in your tsconfig.json file, enabling advanced code transformations during the compilation process.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can use custom transformers in your tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"plugins": [
{ "transform": "./path/to/your/transformer" }
]
}
}
// Unpatch when done
unpatch();
Advanced Compiler Options
This feature allows you to enable advanced compiler options that are not natively supported by TypeScript. By patching the compiler, you can use options like experimental decorators and emit decorator metadata.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can use advanced compiler options in your tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
// Unpatch when done
unpatch();
Integration with Build Tools
This feature allows you to integrate ts-patch with various build tools like Webpack. By patching the TypeScript compiler, you can use custom transformers and advanced compiler options in your build process.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can integrate ts-patch with build tools like Webpack
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
// Unpatch when done
unpatch();
Other packages similar to ts-patch
ttypescript
ttypescript is a fork of the TypeScript compiler that allows you to use custom transformers directly in your tsconfig.json. It is similar to ts-patch in that it enables advanced TypeScript features, but it requires you to use a different compiler binary.
babel-plugin-transform-typescript-metadata
babel-plugin-transform-typescript-metadata is a Babel plugin that adds support for TypeScript metadata reflection. While it doesn't patch the TypeScript compiler, it provides similar functionality by enabling advanced TypeScript features through Babel.
typescript-transform-paths
typescript-transform-paths is a TypeScript transformer that rewrites module paths based on the paths specified in tsconfig.json. It is similar to ts-patch in that it allows for custom transformations, but it focuses specifically on module path rewriting.
ts-patch
Description
ts-patch is a tool which directly patches a typescript installation to allow custom transformers (plugins). Plugins are specified in tsconfig.json
, or provided programmatically in CompilerOptions
.
It now also supports 'transforming' the Program
instance prior to emit. See Transforming Program for more info!
Logic based on ttypescript. It is also fully compatible.
(Credit and thanks to cevek for the excellent work!)
Features
- Easy to patch or unpatch any version of typescript (2.7+)
- One step setup - no complicated install process
- Optionally, enable persistence, which re-patches typescript automatically if it is updated
- Advanced options for patching individual files, specific locations, etc. (see
ts-patch /?
) - Can transform
Program
instance used for emit
Installation
npm i -g ts-patch
Patch
ts-patch install
For more options, use: ts-patch /?
Transformers Usage
tsconfig.json
Add transformers to compilerOptions
in plugin
array:
{
"compilerOptions": {
"plugins": [
{ "transform": "transformer-module" }
]
}
}
Plugin Options
Option | Description |
---|
transform | Module name or path to transformer (*.ts or *.js) |
type | Plugin entry point format (see Plugin Types) |
import | Name of exported transformer function (defaults to default export) |
after | Apply transformer after stock TS transformers. |
afterDeclarations | Apply transformer to declaration (*.d.ts) files (TypeScript 2.9+). |
beforeEmit | Transform Program before program.emit() is called (See Transforming Program) |
... | Provide your own custom options, which will be passed to the transformer |
Note: Required options are bold
Plugin Types
program (default)
Factory signature (program
as first argument):
(program: ts.Program, config: PluginConfig | undefined, helpers: { ts: typeof ts, addDiagnostic: (diag: ts.Diagnostic) => void }) => ts.TransformerFactory
where
ts.TransformerFactory = (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile
Config Example: { "transform": "transformer-module" }
.
Note: addDiagnostic()
can only add Diagnostic
entries to EmitResult.diagnostic
It cannot be used to alter semantic diagnostics
config
Signature with transformer's config:
(config: PluginConfig) => ts.TransformerFactory
Config Example: { "transform": "transformer-module", type: "config" }
.
checker
Signature with ts.TypeChecker:
(checker: ts.TypeChecker, config?: PluginConfig) => ts.TransformerFactory
Config Example: { "transform": "transformer-module", type: "checker" }
.
raw
Signature without factory wrapper:
ts.TransformerFactory
Config Example: { "transform": "transformer-module", type: "raw" }
.
compilerOptions
(compilerOpts: ts.CompilerOptions, config?: PluginConfig) => ts.TransformerFactory
Config Example: { "transform": "transformer-module", type: "compilerOptions" }
.
Examples
{
"compilerOptions": {
"plugins": [
{ "transform": "transformer-module", "someOption1": 123, "someOption2": 321 },
{ "transform": "./transformers/my-transformer.ts" },
{ "transform": "transformer-module1", "after": true },
{ "transform": "transformer-module2", "afterDeclarations": true },
{ "transform": "transformer-module3", "type": "ls" },
{ "transform": "transformer-module4", "beforeEmit": true }
]
}
}
Transforming Program
There are some cases where a transformer isn't enough. Some of the biggest examples are if you're trying to:
- TypeCheck code after it's been transformed
- Add or remove emit files during transformation
In order to do this, you'd normally have to create a custom build tool which manually creates Program
and manipulates
or re-creates it as you need.
The good news is, you can now integrate this into standard tsc behaviour via a beforeEmit
plugin.
Export Signature
(program: ts.Program, host?: ts.CompilerHost, options?: PluginConfig) => ts.Program
Notes
- A Program transformer is not a TS transformer. The signature does not change, so the
type
config option is ignored! - The
before
and after
config options also do not apply if beforeEmit: true
is specified
Example
import * as ts from 'typescript';
import * as path from 'path';
export const newFile = path.resolve(__dirname, 'added-file.ts');
export default function (program: ts.Program, host?: ts.CompilerHost) {
return ts.createProgram(
program.getRootFileNames().concat([ newFile ]),
program.getCompilerOptions(),
host,
program
);
}
Transformers
You can write transformers in TypeScript or JavaScript
import * as ts from 'typescript';
export default function(program: ts.Program, pluginOptions: {}) {
return (ctx: ts.TransformationContext) => {
return (sourceFile: ts.SourceFile) => {
function visitor(node: ts.Node): ts.Node {
return ts.visitEachChild(node, visitor, ctx);
}
return ts.visitEachChild(sourceFile, visitor, ctx);
};
};
}
Example Transformers:
{ "transform": "ts-optchain/transform" }
{transform: "typescript-is/lib/transform-inline/transformer"}
{transform: "ts-transformer-keys/transformer"}
{transform: "ts-transformer-enumerate/transformer"}
{transform: "ts-transform-graphql-tag/dist/transformer"}
{transform: "ts-transform-img/dist/transform", type: "config"}
{transform: "ts-transform-css-modules/dist/transform", type: "config"}
{transform: "ts-transform-react-intl/dist/transform", import: "transform", type: "config"}
{transform: "ts-nameof", type: "raw"}
{transform: "typescript-transform-jsx" }
{transform: "typescript-transform-paths" }
{transform: "typescript-transform-macros" }
{transform: "ts-transformer-minify-privates" }
{transform: "typescript-plugin-styled-components", type: "config"}
{ "transform": "@zoltu/typescript-transformer-append-js-extension" }
Helpful Links
Authors
License
This project is licensed under the MIT License