npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts-const-value-transformer

v0.10.1

Published

Transforms constant variables with actual literals in TypeScript project.

Downloads

575

Readme

ts-const-value-transformer

Transforms constant variables with actual literals in TypeScript project. Provides 'transformer' for TypeScript building ecosystems, 'loader' for webpack, and transform and print APIs.

Motivation

Usually, constant variables will be replaced with actual values by terser, swc or etc. (swc example), but if the variables are exported, the variables are not replaced (swc example). But if the variables are strictly typed, the variables should be replaced probably safely.
This package aims to replace those variables/property references/enum values with actual values, to reduce code side (and, perhaps, to increase execution speed).

Usage

First, install with:

npm install --save-dev ts-const-value-transformer

Using transformer

Transformer is a feature for TypeScript build system to convert parsed source code (AST) to another AST. TypeScript compiler tsc does not accept transformers, but some TypeScript-related ecosystems such as ts-loader and ts-patch accept transformers to intercept builds.

To use with ts-loader, write webpack configuration as follows:

import { createTransformer } from 'ts-const-value-transformer';
// or: const { createTransformer } = require('ts-const-value-transformer');
// (you can use 'require' for ES modules starting from Node.js v20.19.0; see https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require)

const yourWebpackConfiguration = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              getCustomTransformers: (program) => ({
                before: [
                  createTransformer(program, {
                    options: {
                      /* ts-const-value-transformer options (see below) */
                    },
                  }),
                ],
              }),
              // ...other configurations
            },
          },
        ],
      },
    ],
  },
  // ...other configurations
};

or:

const yourWebpackConfiguration = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              // If you specify only one transformer, you can use 'ts-const-value-transformer/getCustomTransformers' module
              getCustomTransformers:
                'ts-const-value-transformer/getCustomTransformers',
              // ...other configurations
            },
          },
        ],
      },
    ],
  },
  // ...other configurations
};

To use with ts-patch, write tsconfig.json as follows:

  "compilerOptions": {
    // ...
    "plugins": [
      { "transform": "ts-const-value-transformer", "options": { /* ts-const-value-transformer options (see below) */ } }
    ]
  }

Using webpack loader

You can use webpack loader for transformation. If you use loaders to transpile TS files other than ts-loader, ts-const-value-transformer/loader is a choice.
Note that this may increase the build time because of parsing processes.

If you are using ts-loader, you should use the transformer described above for performance reason.

const yourWebpackConfiguration = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-typescript'],
            },
          },
          {
            loader: 'ts-const-value-transformer/loader',
            options; {
              project: 'tsconfig.json', // your tsconfig.json
              // typescript: 'typescript', // if you are using another 'typescript' package, you can specify the module name here
              // ... other options from `TransformOptions` fields
              // hoistProperty: false,
              // ...
            }
          },
        ],
      },
    ],
  },
  // ...other configurations
};

Transform options

export interface TransformOptions {
  /** `typescript` namespace object */
  ts?: typeof ts;
  /** Hoist property expressions (`x.prop`) which the value is constant. Default is true, but if the property getter has side effects (not recommended), set false explicitly. */
  hoistProperty?: boolean | undefined;
  /** Hoist TypeScript's `enum` values (which are constant). Default is true, but if you want to preserve references, set false explicitly. Note that TypeScript compiler erases `const enum` references unless `preserveConstEnums` is true. */
  hoistEnumValues?: boolean | undefined;
  /** Hoist values defined in the external libraries. Default is true, but if the external libraries are not bundled, set false explicitly to keep references. */
  hoistExternalValues?: boolean | undefined;
  /** Hoist function calls which the return value is constant. Default is false because function calls may have side effects. */
  unsafeHoistFunctionCall?: boolean | undefined;
  /** Hoist function calls, with `@__PURE__` (or `#__PURE__`) comment annotation (must be a multi-line comment), which the return value is constant. Default is false, but if the function really has no side effects, you can safely specify true. If true, `unsafeHoistFunctionCall` option is ignored for `@__PURE__` functions */
  hoistPureFunctionCall?: boolean | undefined;
  /** Hoist expressions with `as XXX`. Default is false because the base (non-`as`) value may be non-constant. */
  unsafeHoistAsExpresion?: boolean | undefined;
  /** Hoist properties/variables that can write (i.e. `let` / `var` variables or properies without `readonly`). Default is false because although the value is literal type at some point, the value may change to another literal type. */
  unsafeHoistWritableValues?: boolean | undefined;
  /** Uses `undefined` symbol for `undefined` type values. Default is false and replaces to `void 0`. */
  useUndefinedSymbolForUndefinedValue?: boolean | undefined;
  /** Hoist `undefined` symbol to `void 0` (or `undefined` if useUndefinedSymbolForUndefinedValue is true). Default is true. */
  hoistUndefinedSymbol?: boolean | undefined;
  /** Hoist template literals with constant (not including variables). Default is false because it is not necessary for ES2015 or later; Script minifiers would optimize for those values. For ES5 (which will be deprecated in the future), TypeScript converts template literals to such as `''.concat(...)`, which is not treated as constant values. */
  hoistConstTemplateLiteral?: boolean | undefined;
  /**
   * External names (tested with `.includes()` for string, with `.test()` for RegExp) for `hoistExternalValues` settings (If `hoistExternalValues` is not specified, this setting will be used).
   * - Path separators for input file name are always normalized to '/' internally.
   * - Default is `['/node_modules/']`.
   */
  externalNames?: ReadonlyArray<string | RegExp> | undefined;
  /**
   * Specifies for file name list or function to skip transformation. This option is used by webpack loader, the transformed called from ts-loader, and createPortalTransformer only.
   * - For list, if the token is `string`, the transformation will be skipped if `fileName.indexOf(token) >= 0` is true.
   *   If the token is `RegExp`, the transformation will be skipped if `fileName.indexOf(token) >= 0` is true.
   * - For function, the transformation will be skipped if `fn(fileName)` is true.
   */
  ignoreFiles?:
    | ReadonlyArray<string | RegExp>
    | ((fileName: string) => boolean);
}

Note that you must pass options field to createTransformer function or "plugins" specifier (see above examples).

APIs

import {
  createTransformer,
  printSource,
  printSourceWithMap,
  transformSource,
  version,
  type TransformOptions,
  createPortalTransformer,
  createPortalTransformerSync,
  type CreatePortalTransformerOptions,
  type PortalTransformer,
} from 'ts-const-value-transformer';

createTransformer: (program: ts.Program, config?: { options?: TransformOptions }, extras?: { ts?: typeof ts }) => ts.TransformerFactory<ts.SourceFile>

Used with TypeScript API or ts-loader.

Call example:

import * as path from 'path';
import * as ts from 'typescript';
import { createTransformer } from 'ts-const-value-transformer';

const PROJECT_DIR = path.resolve('.');

// Load tsconfig.json file
const configFile = ts.readJsonConfigFile(
  path.resolve(PROJECT_DIR, 'tsconfig.json'),
  ts.sys.readFile
);
const config = ts.parseJsonSourceFileConfigFileContent(
  configFile,
  ts.sys,
  PROJECT_DIR
);

// Initialize the program
const program = ts.createProgram({
  options: config.options,
  rootNames: config.fileNames,
});

// Load the source file to transform
const fileName = path.resolve(PROJECT_DIR, 'index.mts');
const sourceFile = program.getSourceFile(fileName)!;

// Do transform
const transformer = createTransformer(program);
const result = ts.transform(
  sourceFile,
  [transformer],
  program.getCompilerOptions()
);
const transformedSource = result.transformed[0]!;
// You can emit the transformed code by using `printSource` (see below):
//   console.log(printSource(transformedSource));

printSource: (sourceFile: ts.SourceFile) => string

Prints (generates) source code from SourceFile. The source file must be one generated by transformSource or existing in the TS project (available with getSourceFile() in ts.Program).

printSourceWithMap: (sourceFile: ts.SourceFile, originalSourceName: string, startOfSourceMap?: RawSourceMap) => [string, RawSourceMap]

Prints (generates) source code from SourceFile, along with raw source-map data. The source file must be one generated by transformSource or existing in the TS project (available with getSourceFile() in ts.Program).

  • originalSourceName would be the file name of sourceFile, but you can specify another name.
  • startOfSourceMap is a base source map (if original source file is a generated-content) if available.

transformAndPrintSource: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions) => string

Transforms the source file with TypeScript project and prints a new source code. This acts like combination of transformSource and printSource, but performs in one loop, so if transformed AST is not necessary, this function is suitable.

transformAndPrintSourceWithMap: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, originalSourceName: string, options?: TransformOptions, startOfSourceMap?: RawSourceMap) => [string, RawSourceMap]

Transforms the source file with TypeScript project and prints a new source code. This acts like combination of transformSource and printSourceWithMap, but performs in one loop, so if transformed AST is not necessary, this function is suitable.

  • originalSourceName would be the file name of sourceFile, but you can specify another name.
  • startOfSourceMap is a base source map (if original source file is a generated-content) if available.

transformSource: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext, options?: TransformOptions) => ts.SourceFile

Transforms the source file with TypeScript project. You don't need to call this function directly; use createTransformer or createPortalTransformer instead.

Note that ignoreFiles of options will be ignored for this function.

version: string

The version string of this package.

type TransformOptions

See Transform options.

createPortalTransformer: (options?: CreatePortalTransformerOptions) => Promise

Creates 'portal transformer', which can be used the transformer easily from the code which does not use TypeScript Compiler API.
The return object has transform method with signature: (content: string, fileName: string, sourceMap?: string | RawSourceMap | null, options?: TransformOptions) => [newSource: string, newSourceMap: RawSourceMap | undefined]. You can call to transform TypeScript source code. (Note that this API does not transpile to JavaScript; the output code is still TypeScript code.)

CreatePortalTransformerOptions has a following signature. Also, TransformOptions fields, including ignoreFiles, can be used.

interface CreatePortalTransformerOptions extends TransformOptions {
  /** Path to tsconfig.json. If omitted, `tsconfig.json` will be used. */
  project?: string;
  /** Package path to `typescript` or `typescript` namespace object. */
  typescript?: string | typeof tsNamespace;
  /** The current directory for file search. Also affects to `project` option. */
  cwd?: string;
  /**
   * Speficies the count. When the transformation count reaches this value, `program` instance will be recreated (and count will be reset).
   * This is useful if the project is big and out-of-memory occurs during transformation, but the process may be slower.
   * If 0 or `undefined`, recreation will not be performed.
   */
  recreateProgramOnTransformCount?: number;
  /** Specifies to cache base (original) source code for check if the input is changed. Default is false. */
  cacheBaseSource?: boolean;
  /** Specifies to cache result source code. Default is true (false for webpack loader). If the latter process has cache system, specifies false to reduce memory usage. */
  cacheResult?: boolean;
}

If Promise cannot be used for some reason, use createPortalTransformerSync instead.

createPortalTransformerWithTsLs: (options?: CreatePortalTransformerWithTsLsOptions) => Promise

Experimental: Creates 'portal transformer' like createPortalTransformer, but uses TypeScript language server, including tsgo, as type information provider.

  • To use with tsgo, you must install it like npm install -D @typescript/native-preview.
  • Currently, typescript package is also necessary for parsing source code into AST.
  • Also, tsconfig file must be named with tsconfig.json (it is limitation of language server).

CreatePortalTransformerOptions has a following signature. Also, TransformOptions fields, including ignoreFiles, can be used.

export interface CreatePortalTransformerWithTsLsOptions
  extends TransformOptions {
  /**
   * Command to run language server. The first element is used for command name and following elements are used for `argv`.
   * Default is `['npx', 'tsgo', '--lsp', '--stdio']`.
   */
  command?: readonly string[];
  /** Path to tsconfig.json. If omitted, `tsconfig.json` will be used. **Currently `project` must be path to `tsconfig.json` file name; other than `tsconfig.json` is not supported.** */
  project?: string;
  /** Package path to `typescript` or `typescript` namespace object. This is still necessary to retrieve AST. */
  typescript?: string | typeof tsNamespace;
  /** The current directory for file search. Also affects to `project` option. */
  cwd?: string;
  /** Specifies to cache base (original) source code for check if the input is changed. Default is false. */
  cacheBaseSource?: boolean;
  /** Specifies to cache result source code. Default is true (false for webpack loader). If the latter process has cache system, specifies false to reduce memory usage. */
  cacheResult?: boolean;
}

Notice

Starting from v0.4.0, unsafeHoistWritableValues option is introduced. Since TypeScript sometimes narrows non-constant values to literal types such as:

const resultObject = { success: false };
someFunc1(resultObject);
console.log(resultObject.success); // resultObject.success will be `boolean` type
resultObject.success = false;
someFunc1(resultObject);
console.log(resultObject.success); // resultObject.success will be `false` type, not `boolean`

... so if unsafeHoistWritableValues is true, the second reference of resultObject.success above will be replaced to false, which may not be correct.

Additional notes

I think there should be more optimization methods by using strictly-typed information, like other programming languages.

License

MIT License