# Externs and Exports

## Purpose of Externs


Externs are declarations that tell Closure Compiler the names of
symbols that should not be renamed during advanced compilation.
They are called externs because these symbols are most often defined by
code outside the compilation, such a native code, or third-party
libraries. For this reason, externs often also have type annotations,
so that Closure Compiler can typecheck your use of those symbols.


In general, it is best to think of externs as an API contract between
the implementor and the consumers of some piece of compiled code. The
externs define what the implementor promises to supply, and what the
consumers can depend on using. Both sides need a copy of the contract.

Externs are similar to header files in other languages.

## Externs Syntax


Externs are files that look very much like normal JavaScript annotated
for Closure Compiler. The main difference is that their contents are never printed
as part of the compiled output, so none of the values are meaningful,
only the names and types.

Below is an example of an externs file for a simple library.

```
// The `@externs` annotation is the best way to indicate a file contains externs.

/**
 * @fileoverview Public API of my_math.js.
 * @externs
 */

// Externs often declare global namespaces.

const myMath = {};

// Externs can declare functions, most importantly their names.

/**
 * @param {number} x
 * @param {number} y
 * @return {!myMath.DivResult}
 */
myMath.div = function(x, y) {};  // Note the empty body.

// Externs can contain type declarations, such as classes and interfaces.

/** The result of an integer division. */
myMath.DivResult = class {

  // Constructors are special; member fields can be declared in their bodies.

  constructor() {
    /** @type {number} */
    this.quotient;
    /** @type {number} */
    this.remainder;
  }

  // Methods can be declared as usual; their bodies are meaningless though.

  /** @return {!Array<number>} */
  toPair() {}

};

// Fields and methods can also be declared using prototype notation.

/**
 * @override
 * @param {number=} radix
 */
myMath.DivResult.prototype.toString = function(radix) {};
    
```

### The `--externs` Flag


Generally, the `@externs` annotation is the best way to inform
the compiler that a file contains externs. Such files can be included
as normal source files using the `--js` command-line flag,


However, there is another, older way, to specify externs files. The
`--externs` command-line flag can be used to pass externs
files explicitly. This method is not recommended.

## Using Externs

The externs from above can be consumed as follows.

```
/**
 * @fileoverview Do some math.
 */

/**
 * @param {number} x
 * @param {number} y
 * @return {number}
 */
export function greatestCommonDivisor(x, y) {
  while (y != 0) {
    const temp = y;
    // `myMath` is a global, it and `myMath.div` are never renamed.
    const result = myMath.div(x, y);
    // `remainder` is also never renamed on instances of `DivResult`.
    y = result.remainder;
    x = temp;
  }
  return x;
}
    
```

## Purpose of Exports


Exports are another mechanism for giving symbols consistent names after
compilation. They are less useful than externs and often confusing. For
all but simple cases they are best avoided.


Exports rely on the fact that Closure Compiler doesn't modify string literals.
By assigning an object to a property named using a literal, the object will
be available through that property name even after compilation.


Below is a simple example.

```
/**
 * @fileoverview Do some math.
 */

// Note that the concept of module exports is totally unrelated.

/** @return {number} */
export function myFunction() {
  return 5;
}

// This assignment ensures `myFunctionAlias` will be a global alias exposing `myFunction`,
// even after compilation.

window['myFunctionAlias'] = myFunction;
    
```

If you are using Closure Library, exports can also be declared using the
`goog.exportSymbol` and `goog.exportProperty` functions.


More information is available in the Closure Library documentation of
these functions. However, be aware they have special compiler support
and will be totally transformed in the compiled output.

## Issues with Exports


Exports are different from externs in that they only create an exposed
*alias* for consumers to reference. Within the compiled code, the exported
symbol will still be renamed. For this reason, exported symbols must be
constant, since reassigning them in your code would cause the exposed
alias to point to the wrong thing.


This subtlety in renaming is especially complicated with respect to exported
instance properties.


In theory, exports can allow smaller code-size compared to externs, since long
names can still be changed to shorter ones within your code. In practice,
these improvements are often very minor, and don't justify the confusion exports create.


Exports also don't provide an API for consumers to follow in the way externs do.
Compared to exports, externs document the symbols you intend to expose,
their types, and give you a place to add usage information. Additionally,
if your consumers are also using Closure Compiler, they will need externs to
compile against.