Transpile TypeScript code to JavaScript with Closure annotations.
npx @tessl/cli install tessl/npm-tsickle@0.46.0Tsickle is a TypeScript to Closure Compiler translator that converts TypeScript code into a form acceptable to Google's Closure Compiler. It enables developers to write in TypeScript while taking advantage of Closure Compiler's advanced optimization capabilities by automatically generating Closure-compatible JSDoc annotations, converting ES6 modules to goog.module format, generating externs.js from TypeScript declaration files, translating export statements and enums into Closure-compatible forms, and reprocessing JSDoc comments to ensure compatibility.
npm install tsickleimport { emit, TsickleHost, EmitResult } from "tsickle";For CommonJS:
const { emit, TsickleHost, EmitResult } = require("tsickle");import * as ts from "typescript";
import { emit, TsickleHost } from "tsickle";
// Create TypeScript program
const program = ts.createProgram(["src/index.ts"], {
rootDir: "/project/src",
target: ts.ScriptTarget.ES2015,
module: ts.ModuleKind.CommonJS
});
// Configure tsickle host
const host: TsickleHost = {
shouldSkipTsickleProcessing: (fileName) => false,
shouldIgnoreWarningsForPath: (filePath) => false,
pathToModuleName: (context, importPath) => importPath.replace(/\.tsx?$/, ''),
fileNameToModuleId: (fileName) => fileName,
googmodule: true,
transformTypesToClosure: true,
generateExtraSuppressions: true
};
// Emit transformed code
const result = emit(program, host, (fileName, content) => {
console.log(`Writing ${fileName}`);
require('fs').writeFileSync(fileName, content);
});
if (result.diagnostics.length > 0) {
console.error("Compilation errors:", result.diagnostics);
}Tsickle is built around several key components:
emit() function orchestrates the entire transformation pipelineMain transformation functionality that converts TypeScript programs into Closure-compatible JavaScript with proper JSDoc annotations and module formatting.
function emit(
program: ts.Program,
host: TsickleHost,
writeFile: ts.WriteFileCallback,
targetSourceFile?: ts.SourceFile,
cancellationToken?: ts.CancellationToken,
emitOnlyDtsFiles?: boolean,
customTransformers?: EmitTransformers
): EmitResult;
function mergeEmitResults(emitResults: EmitResult[]): EmitResult;
interface TsickleHost extends GoogModuleProcessorHost, TsMigrationExportsShimProcessorHost, AnnotatorHost {
transformDecorators?: boolean;
transformTypesToClosure?: boolean;
generateTsMigrationExportsShim?: boolean;
addDtsClutzAliases?: boolean;
shouldSkipTsickleProcessing(fileName: string): boolean;
shouldIgnoreWarningsForPath(filePath: string): boolean;
googmodule: boolean;
useDeclarationMergingTransformation?: boolean;
generateExtraSuppressions: boolean;
}Advanced type translation system that converts TypeScript type annotations into Closure Compiler-compatible JSDoc type expressions.
class TypeTranslator {
constructor(host: AnnotatorHost, typeChecker: ts.TypeChecker, node: ts.Node, isForExterns?: boolean);
translate(type: ts.Type): string;
symbolToString(sym: ts.Symbol): string;
isAlwaysUnknownSymbol(symbol: ts.Symbol): boolean;
}
function typeToDebugString(type: ts.Type): string;
function symbolToDebugString(sym: ts.Symbol): string;Converts CommonJS require() imports to goog.module() and goog.require() calls, with support for ES6 module syntax transformation.
interface GoogModuleProcessorHost {
pathToModuleName(context: string, importPath: string): string;
fileNameToModuleId(fileName: string): string;
isJsTranspilation?: boolean;
}
function commonJsToGoogmoduleTransformer(
host: GoogModuleProcessorHost,
modulesManifest: ModulesManifest,
typeChecker: ts.TypeChecker
): ts.TransformerFactory<ts.SourceFile>;Comprehensive JSDoc parsing, transformation, and generation system for maintaining Closure Compiler compatibility.
interface ParsedJSDocComment {
tags: Tag[];
warnings?: string[];
}
function parse(comment: ts.CommentRange): ParsedJSDocComment;
function parseContents(commentText: string): ParsedJSDocComment;
function toString(tags: Tag[], escapeExtraTags?: boolean): string;Handles decorator downleveling and output transformation for Closure Compiler property renaming compatibility.
function decoratorDownlevelTransformer(
typeChecker: ts.TypeChecker,
diagnostics: ts.Diagnostic[]
): ts.TransformerFactory<ts.SourceFile>;
function shouldLower(decorator: ts.Decorator, typeChecker: ts.TypeChecker): boolean;
function hasExportingDecorator(node: ts.Node, typeChecker: ts.TypeChecker): boolean;Generates Closure Compiler extern definitions from TypeScript ambient declarations and .d.ts files.
function generateExterns(
typeChecker: ts.TypeChecker,
sourceFile: ts.SourceFile,
host: AnnotatorHost,
moduleResolutionHost: ts.ModuleResolutionHost,
options: ts.CompilerOptions
): { output: string; diagnostics: ts.Diagnostic[] };
function getGeneratedExterns(
externs: { [fileName: string]: string },
rootDir: string
): string;Core utilities for AST manipulation and transformation support, including helper functions for working with TypeScript nodes and creating Closure-compatible constructs.
function hasModifierFlag(declaration: ts.Declaration, flag: ts.ModifierFlags): boolean;
function isAmbient(node: ts.Node): boolean;
function isDtsFileName(fileName: string): boolean;
function getIdentifierText(identifier: ts.Identifier): string;
function symbolIsValue(tc: ts.TypeChecker, sym: ts.Symbol): boolean;Utilities for path manipulation and normalization, providing cross-platform path handling for module resolution and file system operations.
function isAbsolute(path: string): boolean;
function join(p1: string, p2: string): string;
function dirname(path: string): string;
function relative(base: string, rel: string): string;
function normalize(path: string): string;interface EmitResult extends ts.EmitResult {
modulesManifest: ModulesManifest;
externs: { [moduleId: string]: string };
tsMigrationExportsShimFiles: Map<string, string>;
}
interface EmitTransformers {
beforeTs?: ts.CustomTransformers['before'];
afterTs?: ts.CustomTransformers['after'];
afterDeclarations?: ts.CustomTransformers['afterDeclarations'];
}
interface AnnotatorHost {
logWarning?: (warning: ts.Diagnostic) => void;
pathToModuleName(context: string, importPath: string): string;
untyped?: boolean;
typeBlackListPaths?: Set<string>;
unknownTypesPaths?: Set<string>;
convertIndexImportShorthand?: boolean;
provideExternalModuleDtsNamespace?: boolean;
moduleResolutionHost: ts.ModuleResolutionHost;
options: ts.CompilerOptions;
}
class ModulesManifest {
addManifest(other: ModulesManifest): void;
addModule(fileName: string, module: string): void;
addReferencedModule(fileName: string, resolvedModule: string): void;
getFileNameFromModule(module: string): string;
getReferencedModules(fileName: string): string[];
get modules(): string[];
get fileNames(): string[];
}
interface Tag {
tagName: string;
parameterName?: string;
type?: string;
optional?: boolean;
restParam?: boolean;
}