Tsickle: TypeScript to Closure Translator
Tsickle is a TypeScript transpiler designed to convert TypeScript code into JavaScript with Closure Compiler-compatible JSDoc annotations and module formats (`goog.module`). It serves as an intermediate step in build pipelines that leverage Closure Compiler for advanced optimization and minification, particularly within large-scale applications like those developed by Google and Angular. The current stable version is 0.46.3, and its release cadence is irregular, tied to Angular's development and internal Google needs. Key differentiators include its specialized handling of TypeScript types for Closure's type system, conversion of ES6 modules to `goog.module`, and generation of externs.js from TypeScript definition files, making TypeScript projects amenable to the unique optimization strategies of Closure Compiler. It is explicitly noted as a library intended for integration into larger build systems rather than direct end-user application development, often requiring downstream compatibility with Closure's specific module and type conventions.
Common errors
-
Package "tsickle" has an incompatible peer dependency to "typescript" (requires "~X.Y.Z", would install "A.B.C").
cause The installed TypeScript version (A.B.C) does not match the version range required by Tsickle (~X.Y.Z).fixInstall the TypeScript version compatible with your Tsickle installation. For `tsickle@0.46.3`, run `npm install typescript@4.7.2`. -
error TS2307: Cannot find module '...' or its corresponding type declarations.
cause The `tsconfig.json` file is not correctly configured to include all source files, or module resolution paths are incorrect for your project structure.fixReview the `include`, `exclude`, and `paths` options in your `tsconfig.json`. Ensure all relevant `.ts` files and their dependencies are discoverable by the TypeScript compiler when Tsickle is run. -
Error: unknown argument: --some-unsupported-arg
cause An unrecognized or deprecated command-line argument was passed to the `tsickle` CLI. CLI options can change between versions.fixRun `npx tsickle --help` to view the available command-line options for your installed Tsickle version and update your build scripts accordingly.
Warnings
- breaking The Tsickle repository is officially unsupported since November 2022, with no new commits to master since December 2023, and was frozen starting May 2024. It will not be updated.
- breaking Tsickle converts ES6 modules into Closure's `goog.module` system. This is a fundamental transformation that impacts module loading and compatibility with other JavaScript environments.
- gotcha Tsickle's output JavaScript is specifically designed as an intermediate form for the Closure Compiler and is not intended for human readability. It can appear 'ugly' due to heavy JSDoc annotations and transformations.
- gotcha Strict peer dependency on specific TypeScript versions. Using an incompatible TypeScript version can lead to compilation errors or unexpected behavior. For instance, `tsickle@0.46.3` requires `typescript@~4.7.2`.
- gotcha The `declare` keyword in TypeScript (or `.d.ts` files) is crucial for Tsickle to inform Closure Compiler which names must be preserved during minification. Neglecting `declare` for external interfaces or JSON properties can lead to runtime errors due to name mangling.
Install
-
npm install tsickle -
yarn add tsickle -
pnpm add tsickle
Imports
- runTsickle
import { runTsickle } from 'tsickle'; - Options
import { Options } from 'tsickle'; - Tsickle CLI
node_modules/tsickle/src/cli.js
npx tsickle -p tsconfig.json
Quickstart
{
"name": "tsickle-demo",
"version": "1.0.0",
"scripts": {
"build:tsickle": "npx tsickle -p tsconfig.json"
},
"devDependencies": {
"tsickle": "^0.46.3",
"typescript": "~4.7.2"
}
}
// tsconfig.json
{
"compilerOptions": {
"target": "es2017",
"module": "esnext",
"outDir": "dist",
"declaration": true,
"strict": true,
"lib": ["es2017"],
"allowJs": true
},
"include": ["src/**/*.ts"]
}
// src/greeter.ts
/**
* @fileoverview A simple class to demonstrate Tsickle conversion.
*/
export class Greeter {
/** @type {string} */
private readonly name: string;
/**
* @param {string} name The name to greet.
*/
constructor(name: string) {
this.name = name;
}
/**
* Generates a greeting message.
* @return {string} The greeting.
*/
greet(): string {
return `Hello, ${this.name}!`;
}
}
// To run this example:
// 1. Create the files above in your project root.
// 2. Run `npm install`
// 3. Run `npm run build:tsickle`
// This will output Closure-annotated JavaScript to the `dist` directory.