ts-patch
ts-patch is a utility that augments the TypeScript compiler to enable the use of custom Abstract Syntax Tree (AST) transformers and plugins during the build process. It allows developers to specify these transformers directly within `tsconfig.json` or to provide them programmatically via `CompilerOptions`. The current stable version is 3.3.0, with frequent releases to ensure compatibility with the latest TypeScript versions, such as adding support for TypeScript 5.7+ in the most recent update. Key differentiators include its dual approach to patching: an on-the-fly 'live compiler' (accessed via `tspc` or by specifying `ts-patch/compiler` in build tools) and a 'persistent patch' method that modifies the `node_modules` installation. It offers full compatibility with legacy `ttypescript` projects and supports both source-level and program-level transformations, with experimental support for ES Module-based transformers.
Common errors
-
Error: Cannot find module 'ts-patch/compiler'
cause The build tool (e.g., ts-node, webpack, Jest) is not correctly configured to use `ts-patch/compiler` as its TypeScript compiler.fixEnsure your build tool's configuration points to `ts-patch/compiler` as the compiler path. For example, `ts-node --compiler ts-patch/compiler` or in `jest.config.js`: `globals['ts-jest'].compiler = 'ts-patch/compiler'`. -
TypeError: Cannot read properties of undefined (reading 'createSourceFile') or similar errors related to TypeScript API
cause Your `ts-patch` version is incompatible with your installed `typescript` version, or the persistent patch was not applied.fixUpdate `ts-patch` to the latest version. If using persistent patching, ensure `npm run prepare` (or `ts-patch install`) has been run successfully after `npm install`. -
Plugin 'your-transformer-module' not found. Make sure it's installed or the path is correct.
cause The transformer module specified in `tsconfig.json`'s `plugins` array is either not installed, the path is incorrect, or it cannot be resolved by Node.js module resolution.fixVerify the transformer module's name in `tsconfig.json` is correct and it is listed in `package.json` dependencies. If it's a local file, ensure the path is relative to `tsconfig.json` and includes the `.ts` or `.js` extension if not directly resolvable. -
ENOENT: no such file or directory, stat '/path/to/node_modules/typescript/lib/typescript.js.bak'
cause This error can occur if `ts-patch` attempts to restore a backup of `typescript.js` but the backup file is missing, likely due to manual deletion or an interrupted `ts-patch uninstall`.fixTry running `ts-patch uninstall` if you believe it's partially unpatched. If problems persist, a fresh `rm -rf node_modules && npm install` followed by `ts-patch install` might be necessary. This specific issue was also addressed in v3.0.1 with a more explicit error.
Warnings
- breaking ts-patch requires frequent updates to maintain compatibility with new TypeScript versions. Using an older `ts-patch` version with a newer `typescript` compiler can lead to build failures or unexpected behavior. For example, v3.2.0 added support for TS 5.5, and v3.3.0 for TS 5.7+.
- gotcha The 'persistent patch' method (`ts-patch install`) modifies your `node_modules/typescript` installation. If `node_modules` is cleared or reinstalled (e.g., in CI/CD environments or by package managers), the patch will be lost, leading to build errors.
- deprecated The `beforeEmit` option for Program Transformers has been renamed to `transformProgram` to better reflect its behavior. While `beforeEmit` still functions as an alias, using the new `transformProgram` is recommended for clarity and future compatibility.
- gotcha When using `ts-patch` in build tools like `ts-node`, `webpack` (via `ts-loader`), or `Jest` (via `ts-jest`), you must explicitly configure them to use `ts-patch/compiler` as the TypeScript compiler. Failing to do so will result in custom transformers not being applied.
Install
-
npm install ts-patch -
yarn add ts-patch -
pnpm add ts-patch
Imports
- patch
const patch = require('ts-patch').patch;import { patch } from 'ts-patch'; - unpatch
const unpatch = require('ts-patch').unpatch;import { unpatch } from 'ts-patch'; - createProgram
import { createProgram } from 'ts-patch/compiler';import createProgram from 'ts-patch/compiler';
Quickstart
import * as ts from 'typescript';
// 1. Define a simple TypeScript AST transformer
// This transformer appends a comment to every variable statement.
const myTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
return (rootNode) => {
function visit(node: ts.Node): ts.Node {
if (ts.isVariableStatement(node)) {
// Add a synthetic leading comment to the variable statement
const commentText = '/** Transformed by ts-patch **/ ';
return ts.addSyntheticLeadingComment(
node,
ts.SyntaxKind.MultiLineCommentTrivia,
commentText,
true // New line after comment
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
};
export default myTransformer;
// tsconfig.json
// {
// "compilerOptions": {
// "target": "es2018",
// "module": "commonjs",
// "outDir": "./dist",
// "strict": true,
// "plugins": [
// { "transform": "./my-transformer.ts" }
// ]
// }
// }
// src/index.ts
// const appName = "My Awesome App";
// console.log(`Welcome to ${appName}`);
// To run:
// 1. npm install -D typescript ts-patch
// 2. Create my-transformer.ts, tsconfig.json, and src/index.ts as above.
// 3. From your terminal, run: npx ts-patch install
// 4. Then compile: npx tspc
// 5. Check 'dist/index.js' for the added comment.