AlCalzone / ts-patch

Augment the TypeScript compiler to support extended functionality

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

npm version NPM Downloads Build Status

TS Patch

Directly patch typescript installation to allow custom transformers (plugins).

  • Plugins are specified in tsconfig.json, or provided programmatically in CompilerOptions.
  • Based on ttypescript - Fully compatible + offers more features

TypeScript v5 Note

TS v5 has made some fundamental changes which affect the current process. As a result, it is not yet supported.

We're working on adding support. More notes on that here:

Features

  • Patch / unpatch any version of typescript (4.*)
  • Advanced options for patching individual libraries, specific locations, etc. (see ts-patch /?)
  • (New) Supports 'transforming' the Program instance during creation. (see: Transforming Program)
  • (New) Add, remove, or modify diagnostics! (see: Altering Diagnostics)

Setup

  1. Install package
<yarn|npm|pnpm> add -D ts-patch
  1. Patch typescript
# For advanced options, see: ts-patch /?
ts-patch install
  1. Add prepare script (keeps patch persisted after npm install)

package.json

{
 /* ... */
 "scripts": {
   "prepare": "ts-patch install -s"
 }
}

Table of Contents

Configuring

tsconfig.json

Add transformers to compilerOptions in plugins array.

Examples

{
    "compilerOptions": {
        "plugins": [
            // Source Transformer: 'type' defaults to 'program'
            { "transform": "transformer-module", "someOption1": 123, "someOption2": 321 },

            // Source Transformer: program signature 
            { "transform": "./transformers/my-transformer.ts", "type": "program" },

            // Source Transformer: program signature, applies after TS transformers
            { "transform": "transformer-module1", "type": "config", "after": true },

            // Source Transformer: checker signature, applies to TS declarations
            { "transform": "transformer-module2", "type": "checker", "afterDeclarations": true }, 
            
            // Source Transformer: raw signature
            { "transform": "transformer-module3", "type": "raw" },

            // Source Transformer: compilerOptions signature 
            { "transform": "transformer-module4", "type": "compilerOptions" },

            // Program Transformer: Only has one signature - no type specified, because it does not apply
            { "transform": "transformer-module5", "transformProgram": true }
        ]
    }
}

Plugin Options

Option Type Description
transform string Module name or path to transformer (*.ts or *.js)
type string Source Transformer entry point signature (see: Source Transformer Signatures)
import string Name of exported transformer function (defaults to default export)
tsConfig string tsconfig.json file for transformer (allows specifying compileOptions, path mapping support, etc)
after boolean Apply transformer after stock TS transformers.
afterDeclarations boolean Apply transformer to declaration (*.d.ts) files (TypeScript 2.9+).
transformProgram boolean Transform Program during ts.createProgram() (see: Transforming Program)
... Provide your own custom options, which will be passed to the transformer

Note: Required options are bold

Source Transformer Signatures

The following are the possible values for the type option and their corresponding entry point signatures.
Note: These apply to Source Transformers only.

program (default)

Signature with ts.Program instance:

(program: ts.Program, config: PluginConfig, extras: TransformerExtras) => ts.TransformerFactory

ts.TransformerFactory >>> (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile
TransformerExtras >>> See Type Declaration

Note: This is not the configuration for a Program Transformer.

config

Signature with transformer's config:

(config: PluginConfig) => ts.TransformerFactory

checker

Signature with ts.TypeChecker:

(checker: ts.TypeChecker, config: PluginConfig) => ts.TransformerFactory

raw

Signature without ts-patch wrapper:

/* ts.TransformerFactory */ 
(context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile

compilerOptions

(compilerOpts: ts.CompilerOptions, config: PluginConfig) => ts.TransformerFactory

Usage

Transforming AST Nodes

Transformers can be written in JS or TS.

// transformer1-module
import * as ts from 'typescript';
export default function(program: ts.Program, pluginOptions: any) {
    return (ctx: ts.TransformationContext) => {
        return (sourceFile: ts.SourceFile) => {
            function visitor(node: ts.Node): ts.Node {
                // if (ts.isCallExpression(node)) {
                //     return ts.createLiteral('call');
                // }
                return ts.visitEachChild(node, visitor, ctx);
            }
            return ts.visitEachChild(sourceFile, visitor, ctx);
        };
    };
}

Example Node Transformers

{ transform: "typescript-transform-paths" }

{ transform: "typescript-is/lib/transform-inline/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: "ts-transformer-minify-privates" }

{ transform: "typia/lib/transform" }

Transforming Program

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 allows re-creating the Program instance that typescript uses.

Configuring Program Transformer

To configure a Program Transformer, supply "transformProgram": true in the config transformer entry.

Note: The type, before, and after options do not apply to a Program Transformer and will be ignored

See Config Example

Signature

There is only one possible signature for a Program Transformer entry point.

(program: ts.Program, host: ts.CompilerHost | undefined, options: PluginConfig, extras: ProgramTransformerExtras) => ts.Program

ProgramTransformerExtras >>> See Type Declaration

Example Program Transformer

/** 
 * Add a file to Program
 */
import * as ts from 'typescript';
import * as path from 'path';
import { 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

Altering Diagnostics

Diagnostics can be altered in a Source Transformer.

To alter diagnostics, use the program type signature, and use the following properties from the TransformerExtras parameter

property description
diagnostics Reference to Diagnostic array
addDiagnostic() Directly add Diagnostic to diagnostics array
removeDiagnostic() Directly remove Diagnostic from diagnostics array (uses splice, for safe removal)

Notes

  • 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

Resources

Recommended Reading

Recommended Tools

Tool Type Description
TS AST Viewer Website Allows you to see the Node structure and other TS properties of your source code.
ts-query NPM Package Perform fast CSS-like queries on AST to find specific nodes (by attribute, kind, name, etc)
ts-query Playground Website Test ts-query in realtime
ts-expose-internals NPM Package Exposes internal types and methods of the TS compiler API

Credit

Author Module
Ron S. ts-patch
cevek ttypescript

HALP!!!

License

This project is licensed under the MIT License, as described in LICENSE.md

About

Augment the TypeScript compiler to support extended functionality

License:MIT License


Languages

Language:TypeScript 97.3%Language:JavaScript 2.7%