tsickle
Version:
Transpile TypeScript code to JavaScript with Closure annotations.
87 lines (86 loc) • 4.15 kB
TypeScript
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @fileoverview Externs creates Closure Compiler #externs definitions from the
* ambient declarations in a TypeScript file.
*
* (Note that we cannot write the "@" form of the externs tag, even in comments,
* because the compiler greps for it in source files(!). So we write #externs
* instead.)
*
* For example, a
* declare interface Foo { bar: string; }
*
* Would generate a
* /.. #externs ./
* /.. @record ./
* var Foo = function() {};
* /.. @type {string} ./
* Foo.prototype.bar;
*
* The generated externs indicate to Closure Compiler that symbols are external
* to the optimization process, i.e. they are provided by outside code. That
* most importantly means they must not be renamed or removed.
*
* A major difficulty here is that TypeScript supports module-scoped external
* symbols; `.d.ts` files can contain `export`s and `import` other files.
* Closure Compiler does not have such a concept, so tsickle must emulate the
* behaviour. It does so by following this scheme:
*
* 1. non-module .d.ts produces global symbols
* 2. module .d.ts produce symbols namespaced to the module, by creating a
* mangled name matching the current file's path. tsickle expects outside
* code (e.g. build system integration or manually written code) to contain a
* goog.module/provide that references the mangled path.
* 3. declarations in `.ts` files produce types that can be separately emitted
* in e.g. an `externs.js`, using `getGeneratedExterns` below.
* 1. non-exported symbols produce global types, because that's what users
* expect and it matches TypeScripts emit, which just references `Foo` for
* a locally declared symbol `Foo` in a module. Arguably these should be
* wrapped in `declare global { ... }`.
* 2. exported symbols are scoped to the `.ts` file by prefixing them with a
* mangled name. Exported types are re-exported from the JavaScript
* `goog.module`, allowing downstream code to reference them. This has the
* same problem regarding ambient values as above, it is unclear where the
* value symbol would be defined, so for the time being this is
* unsupported.
*
* The effect of this is that:
* - symbols in a module (i.e. not globals) are generally scoped to the local
* module using a mangled name, preventing symbol collisions on the Closure
* side.
* - importing code can unconditionally refer to and import any symbol defined
* in a module `X` as `path.to.module.X`, regardless of whether the defining
* location is a `.d.ts` file or a `.ts` file, and regardless whether the
* symbol is ambient (assuming there's an appropriate shim).
* - if there is a shim present, tsickle avoids emitting the Closure namespace
* itself, expecting the shim to provide the namespace and initialize it to a
* symbol that provides the right value at runtime (i.e. the implementation of
* whatever third party library the .d.ts describes).
*/
import * as ts from 'typescript';
import { AnnotatorHost } from './annotator_host';
/**
* Concatenate all generated externs definitions together into a string,
* including a file comment header.
*
* @param rootDir Project root. Emitted comments will reference paths relative
* to this root.
*/
export declare function getGeneratedExterns(externs: {
[fileName: string]: string;
}, rootDir: string): string;
/**
* generateExterns generates extern definitions for all ambient declarations in the given source
* file. It returns a string representation of the Closure JavaScript, not including the initial
* comment with \@fileoverview and #externs (see above for that).
*/
export declare function generateExterns(typeChecker: ts.TypeChecker, sourceFile: ts.SourceFile, host: AnnotatorHost, moduleResolutionHost: ts.ModuleResolutionHost, options: ts.CompilerOptions): {
output: string;
diagnostics: ts.Diagnostic[];
};