Programmatic TypeScript Compiler
`tsc-prog` is a JavaScript/TypeScript library designed to programmatically build TypeScript projects. It offers a flexible API for invoking the TypeScript compiler (`tsc`) with granular control over the build process, going beyond simple CLI execution. This library is particularly suited for complex production build pipelines where custom logic, pre-build steps, or post-build steps are required. Key features include a simplified `build` function, direct access to TypeScript's `Program` creation and `emit` steps, and powerful addons. These addons address common TypeScript build pain points like cleaning output directories (`clean` option), copying non-TypeScript assets to the output directory (`copyOtherToOutDir`), and bundling type definitions into a single `.d.ts` file (`bundleDeclaration`). As of version 2.3.0, `tsc-prog` primarily operates as a CommonJS module and requires `typescript@>=4` as a peer dependency. While it doesn't specify a strict release cadence, updates appear as needed to support new TypeScript features or address build complexities.
Common errors
-
Cannot find module 'tsc-prog'
cause The package is not installed or the `require()` path is incorrect.fixRun `npm install --save-dev tsc-prog` or `yarn add --dev tsc-prog`. Ensure your Node.js environment resolves modules correctly if using custom module resolution. -
TypeError: tsc.build is not a function
cause Attempting to use `tsc.build` after an incorrect import (e.g., a named ESM import on a CJS module) or a corrupted package installation.fixEnsure you are using `const tsc = require('tsc-prog')` to correctly import the CommonJS module. If the problem persists, try reinstalling the package. -
Error: Parameter 'outDir' is required for 'copyOtherToOutDir'
cause The `copyOtherToOutDir` option was enabled, but `compilerOptions.outDir` was not provided or was empty.fixAdd `outDir` to your `compilerOptions`. Example: `compilerOptions: { outDir: 'dist', ... }, copyOtherToOutDir: true`. -
Error: Parameter 'declaration' must be true in 'compilerOptions' for 'bundleDeclaration'
cause The `bundleDeclaration` option was enabled, but `compilerOptions.declaration` was not set to `true`.fixSet `declaration: true` in your `compilerOptions`. Example: `compilerOptions: { declaration: true, ... }, bundleDeclaration: { entryPoint: 'index.d.ts' }`.
Warnings
- gotcha tsc-prog is a CommonJS module. Ensure you use `require()` for imports in your Node.js projects, especially if your project is also CommonJS. Direct ESM `import` statements will fail unless explicitly transpiled or if Node.js runtime handles CJS interop for ESM, which is not guaranteed for older Node.js versions.
- breaking Future versions (v3+) may transition to an ESM-first or ESM-only approach. This would be a breaking change, requiring updates to import statements and potentially project `type` configurations in `package.json`.
- gotcha The `clean` option has built-in protections preventing deletion of critical directories like `basePath`, current working directory, or `rootDir` and their parents. This is a safety feature, but if you intend to delete a parent directory that matches these patterns, the operation will be skipped or partially applied.
- gotcha When using `copyOtherToOutDir`, `outDir` must be explicitly set in your `compilerOptions`. If `outDir` is missing, the option will have no effect or may cause errors.
- gotcha For `bundleDeclaration` to work, `compilerOptions.declaration` must be set to `true`, and `entryPoint` is relative to the *output* directory (`outDir`). Misconfiguring these can lead to failed bundling or incorrect output paths.
Install
-
npm install tsc-prog -
yarn add tsc-prog -
pnpm add tsc-prog
Imports
- tsc
import tsc from 'tsc-prog'
const tsc = require('tsc-prog') - build
import { build } from 'tsc-prog'const tsc = require('tsc-prog'); tsc.build({...}) - createProgramFromConfig
import { createProgramFromConfig } from 'tsc-prog'const tsc = require('tsc-prog'); tsc.createProgramFromConfig({...})
Quickstart
const tsc = require('tsc-prog');
const path = require('path');
const fs = require('fs');
const basePath = path.resolve(__dirname, 'temp_project');
const tsconfigPath = path.join(basePath, 'tsconfig.json');
const srcDir = path.join(basePath, 'src');
const outDir = path.join(basePath, 'dist');
// Ensure directories exist
fs.mkdirSync(srcDir, { recursive: true });
fs.mkdirSync(outDir, { recursive: true });
// Create a dummy tsconfig.json
fs.writeFileSync(tsconfigPath, JSON.stringify({
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true
},
"include": ["src/**/*"]
}, null, 2));
// Create a dummy TypeScript file
fs.writeFileSync(path.join(srcDir, 'index.ts'), 'export function greet(name: string) { return `Hello, ${name}!`; }');
fs.writeFileSync(path.join(srcDir, 'main.ts'), 'import { greet } from "./index"; console.log(greet("World"));');
console.log('Building TypeScript project with tsc-prog...');
tsc.build({
basePath: basePath,
configFilePath: 'tsconfig.json',
compilerOptions: {
rootDir: 'src',
outDir: 'dist',
declaration: true,
skipLibCheck: true,
},
include: ['src/**/*'],
exclude: ['**/*.test.ts', '**/*.spec.ts'],
clean: ['dist'], // Clean previous build artifacts
copyOtherToOutDir: true, // Copy non-TS files if any (e.g., package.json)
});
console.log('Build complete. Check the temp_project/dist directory.');
// Cleanup (optional)
// fs.rmSync(basePath, { recursive: true, force: true });