JavaScript-Code für den Closure Compiler annotieren

Hinweis: Diese Seite ist veraltet. Die vollständige Liste finden Sie unter https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler .

Übersicht

Der Closure Compiler kann Datentypinformationen zu JavaScript-Variablen verwenden, um die Optimierung und Warnungen zu verbessern. In JavaScript gibt es jedoch keine Möglichkeit, Typen zu deklarieren.

Da es in JavaScript keine Syntax zum Deklarieren des Typs einer Variablen gibt, müssen Sie Kommentare im Code verwenden, um den Datentyp anzugeben.

Die Typsprache des Closure Compilers leitet sich von den Anmerkungen ab, die vom Tool zur Dokumentgenerierung JSDoc verwendet werden. Sie hat sich jedoch inzwischen weiterentwickelt. Es enthält jetzt mehrere Annotationen, die JSDoc nicht unterstützt, und umgekehrt. In diesem Dokument werden die Anmerkungen und Typausdrücke beschrieben, die der Closure Compiler versteht.

  1. JSDoc-Tags
  2. Typausdrücke
  3. Generische Typen

JSDoc-Tags

Der Closure Compiler sucht nach Typinformationen in JSDoc-Tags. Verwenden Sie die in der Referenztabelle unten beschriebenen JSDoc-Tags, damit der Compiler Ihren Code optimieren und auf mögliche Typfehler und andere Fehler prüfen kann.

Diese Tabelle enthält nur Tags, die sich auf das Verhalten des Closure Compilers auswirken. Informationen zu anderen JSDoc-Tags finden Sie in der JSDoc Toolkit-Dokumentation.

Tag Beschreibung
@abstract

Kennzeichnet eine Methode als abstrakt. Ähnlich wie beim Festlegen einer Methode auf goog.abstractMethod kann der Compiler Methoden, die mit @abstract annotiert sind, entfernen, um die Codegröße zu reduzieren.

Der Compiler gibt eine Warnung aus, wenn eine mit @abstract markierte Methode eine nicht leere Implementierung hat.

Beispiel:
/** @abstract */
foo.MyClass.prototype.abstractMethod = function() {};
@const

Markiert eine Variable als schreibgeschützt. Der Compiler kann @const-Variablen inline einfügen, wodurch der JavaScript-Code optimiert wird.

Die Typdeklaration ist optional.

Der Compiler gibt eine Warnung aus, wenn einer mit @const gekennzeichneten Variablen mehr als einmal ein Wert zugewiesen wird. Wenn die Variable ein Objekt ist, werden Änderungen an den Eigenschaften des Objekts vom Compiler nicht verhindert.

Beispiel:
/** @const */ var MY_BEER = 'stout';

/**
 * My namespace's favorite kind of beer.
 * @const {string}
 */
mynamespace.MY_BEER = 'stout';

/** @const */ MyClass.MY_BEER = 'stout';
@constructor

Markiert eine Funktion als Konstruktor. Der Compiler erfordert eine @constructor-Annotation für jede Funktion, die mit dem Schlüsselwort new verwendet wird.

Beispiel:

/**
 * A rectangle.
 * @constructor
 */
function GM_Rect() {
  ...
}
@define Gibt eine Konstante an, die vom Compiler zur Kompilierzeit überschrieben werden kann. Im Beispiel auf der linken Seite können Sie das Flag --define='ENABLE_DEBUG=false' an den Compiler übergeben, um den Wert von ENABLE_DEBUG in false zu ändern. Der Typ einer definierten Konstanten kann „number“, „string“ oder „boolean“ sein. Defines sind nur im globalen Bereich zulässig.

Beispiel:

/** @define {boolean} */
var ENABLE_DEBUG = true;

/** @define {boolean} */
goog.userAgent.ASSUME_IE = false;
@deprecated

Markiert eine Funktion, Methode oder Eigenschaft, sodass bei der Verwendung eine Compilerwarnung ausgegeben wird, die darauf hinweist, dass sie nicht mehr verwendet werden sollte.

Beispiel:

/**
 * Determines whether a node is a field.
 * @return {boolean} True if the contents of
 *     the element are editable, but the element
 *     itself is not.
 * @deprecated Use isField().
 */
BN_EditUtil.isTopEditableField = function(node) {
  ...
};
@dict

@dict wird verwendet, um Objekte mit einer variablen Anzahl von Eigenschaften zu erstellen. Wenn ein Konstruktor (Foo im Beispiel) mit @dict annotiert ist, können Sie nur die Bracket-Notation verwenden, um auf die Eigenschaften von Foo-Objekten zuzugreifen. Die Anmerkung kann auch direkt für Objektliterale verwendet werden.

Beispiel:

/**
 * @constructor
 * @dict
 */
function Foo() {}
var obj1 = new Foo();
obj1['x'] = 123;
obj1.x = 234;  // warning

var obj2 = /** @dict */ { 'x': 321 };
obj2.x = 123;  // warning
@enum

Gibt den Typ einer Enumeration an. Ein Enum ist ein Objekt, dessen Eigenschaften eine Reihe verwandter Konstanten bilden. Auf das @enum-Tag muss ein Typausdruck folgen.

Das Typ-Label eines Enums gilt für jede Property des Enums. Wenn ein Enum beispielsweise den Typ number hat, muss jede seiner aufgezählten Eigenschaften eine Zahl sein. Wenn der Typ einer Enumeration weggelassen wird, wird number angenommen.

Beispiel:

/**
 * Enum for tri-state values.
 * @enum {number}
 */
project.TriState = {
  TRUE: 1,
  FALSE: -1,
  MAYBE: 0
};
@export

Angenommen, Sie haben diesen Code:

/** @export */
foo.MyPublicClass.prototype.myPublicMethod = function() {
  // ...
};

Wenn der Compiler mit dem Flag --generate_exports ausgeführt wird, wird der folgende Code generiert:

goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod',
  foo.MyPublicClass.prototype.myPublicMethod);

Dadurch werden die Symbole in nicht kompilierten Code exportiert. Sie können /** @export {SomeType} */ als Abkürzung für

/**
 * @export
 * @type {SomeType}
 */

Code, der die Annotation @export verwendet, muss entweder

  1. closure/base.js enthalten oder
  2. Definieren Sie sowohl goog.exportSymbol als auch goog.exportProperty mit derselben Methodensignatur in ihrer eigenen Codebasis.
@extends

Markiert eine Klasse oder Schnittstelle als von einer anderen Klasse abgeleitet. Eine mit @extends gekennzeichnete Klasse muss auch mit @constructor oder @interface gekennzeichnet sein.

Hinweis: @extends führt nicht dazu, dass eine Klasse von einer anderen Klasse erbt. Die Annotation teilt dem Compiler lediglich mit, dass er eine Klasse während der Typüberprüfung als Unterklasse einer anderen Klasse behandeln kann.

Ein Beispiel für die Implementierung der Vererbung finden Sie in der Closure-Bibliotheksfunktion goog.inherits().

Beispiel:

/**
 * Immutable empty node list.
 * @constructor
 * @extends {goog.ds.BasicNodeList}
 */
goog.ds.EmptyNodeList = function() {
  ...
};
@final

Gibt an, dass diese Klasse nicht erweitert werden darf. Gibt für Methoden an, dass keine Unterklasse diese Methode überschreiben darf.

Beispiel:

/**
 * A class that cannot be extended.
 * @final
 * @constructor
 */
sloth.MyFinalClass = function() { ... }

/**
 * A method that cannot be overridden.
 * @final
 */
sloth.MyFinalClass.prototype.method = function() { ... };
@implements

Wird mit @constructor verwendet, um anzugeben, dass eine Klasse eine Schnittstelle implementiert.

Der Compiler gibt eine Warnung aus, wenn Sie einen Konstruktor mit @implements kennzeichnen und dann nicht alle Methoden und Eigenschaften implementieren, die vom Interface definiert werden.

Beispiel:

/**
 * A shape.
 * @interface
 */
function Shape() {};
Shape.prototype.draw = function() {};

/**
 * @constructor
 * @implements {Shape}
 */
function Square() {};
Square.prototype.draw = function() {
  ...
};
@implicitCast

Diese Annotation kann nur in externen Property-Deklarationen verwendet werden. Für die Eigenschaft ist ein Typ deklariert, Sie können ihr jedoch ohne Warnung einen beliebigen Typ zuweisen. Beim Zugriff auf die Property wird ein Wert des deklarierten Typs zurückgegeben. element.innerHTML kann beispielsweise ein beliebiger Typ zugewiesen werden, gibt aber immer einen String zurück.

/**
 * @type {string}
 * @implicitCast
 */
Element.prototype.innerHTML;
@inheritDoc

Gibt an, dass eine Methode oder Eigenschaft einer Unterklasse absichtlich eine Methode oder Eigenschaft der Superklasse verbirgt und genau dieselbe Dokumentation hat. Das Tag @inheritDoc impliziert das Tag @override.

Beispiel:

/** @inheritDoc */
project.SubClass.prototype.toString = function() {
  ...
};
@interface

Markiert eine Funktion als Schnittstelle. Eine Schnittstelle gibt die erforderlichen Member eines Typs an. Jede Klasse, die eine Schnittstelle implementiert, muss alle Methoden und Eigenschaften implementieren, die im Prototyp der Schnittstelle definiert sind. Weitere Informationen finden Sie unter @implements.

Der Compiler prüft, ob Schnittstellen instanziiert werden. Wenn das Schlüsselwort new mit einer Schnittstellenfunktion verwendet wird, gibt der Compiler eine Warnung aus.

Beispiel:

/**
 * A shape.
 * @interface
 */
function Shape() {};
Shape.prototype.draw = function() {};

/**
 * A polygon.
 * @interface
 * @extends {Shape}
 */
function Polygon() {};
Polygon.prototype.getSides = function() {};
@lends

Gibt an, dass die Schlüssel eines Objektliterals als Attribute eines anderen Objekts behandelt werden sollen. Diese Anmerkung sollte nur für Objektliterale verwendet werden.

Der Name in geschweiften Klammern ist kein Typname wie in anderen Anmerkungen. Es ist ein Objektname. Es gibt den Namen des Objekts an, dem die Eigenschaften geliehen werden. Beispiel: @type {Foo} bedeutet „eine Instanz von Foo“, @lends {Foo} bedeutet „der Konstruktor Foo“.

Weitere Informationen zu dieser Annotation finden Sie in der JSDoc Toolkit-Dokumentation.

Beispiel:

goog.object.extend(
    Button.prototype,
    /** @lends {Button.prototype} */ ({
      isButton: function() { return true; }
    }));
@license oder @preserve

Weist den Compiler an, den zugehörigen Kommentar vor dem kompilierten Code für die markierte Datei einzufügen. Mit dieser Anmerkung können wichtige Hinweise (z. B. rechtliche Lizenzen oder Urheberrechtstext) unverändert in die Kompilierung übernommen werden. Zeilenumbrüche werden beibehalten.

Beispiel:

/**
 * @preserve Copyright 2009 SomeThirdParty.
 * Here is the full license text and copyright
 * notice for this file. Note that the notice can span several
 * lines and is only terminated by the closing star and slash:
 */
@nocollapse

Gibt ein Attribut an, das vom Compiler nicht in einer Variablen zusammengefasst werden soll. @nocollapse wird hauptsächlich verwendet, um den Export von veränderlichen Attributen zu ermöglichen. Beachten Sie, dass nicht minimierte Eigenschaften weiterhin vom Compiler umbenannt werden können. Wenn Sie eine Eigenschaft, die ein Objekt ist, mit @nocollapse annotieren, bleiben auch alle zugehörigen Eigenschaften aufgeklappt.

Beispiel:

/**
 * A namespace.
 * @const
 */
var foo = {};

/**
 * @nocollapse
 */
foo.bar = 42;

window['foobar'] = foo.bar;
@nosideeffects

Gibt an, dass ein Aufruf der deklarierten externen Funktion keine Nebenwirkungen hat. Mit dieser Anmerkung kann der Compiler Aufrufe der Funktion entfernen, wenn der Rückgabewert nicht verwendet wird. Die Anmerkung ist nur in extern files zulässig.

Beispiel:

/** @nosideeffects */
function noSideEffectsFn1() {}

/** @nosideeffects */
var noSideEffectsFn2 = function() {};

/** @nosideeffects */
a.prototype.noSideEffectsFn3 = function() {};
@override

Gibt an, dass eine Methode oder Eigenschaft einer Unterklasse absichtlich eine Methode oder Eigenschaft der Superklasse ausblendet. Wenn keine anderen Annotationen enthalten sind, erbt die Methode oder das Attribut automatisch Annotationen von der zugehörigen Superklasse.

Beispiel:

/**
 * @return {string} Human-readable representation of
 *     project.SubClass.
 * @override
 */
project.SubClass.prototype.toString = function() {
  ...
};
@package

Kennzeichnet ein Mitglied oder eine Eigenschaft als „package private“. Nur Code im selben Verzeichnis kann auf Namen zugreifen, die mit @package gekennzeichnet sind. Insbesondere kann Code in übergeordneten und untergeordneten Verzeichnissen nicht auf Namen zugreifen, die mit @package gekennzeichnet sind.

Öffentliche Konstruktoren können @package-Attribute haben, um die Methoden einzuschränken, die von Aufrufern außerhalb des Verzeichnisses verwendet werden können. @package-Konstruktoren können hingegen öffentliche Eigenschaften haben, um zu verhindern, dass Aufrufer außerhalb des Verzeichnisses einen Typ direkt instanziieren.

Beispiel:

/**
 * Returns the window object the foreign document resides in.
 *
 * @return {Object} The window object of the peer.
 * @package
 */
goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() {
  // ...
};
@param

Wird mit Methoden-, Funktions- und Konstruktordefinitionen verwendet, um die Typen von Funktionsargumenten anzugeben. @param-Tags müssen in derselben Reihenfolge wie die Parameter in der Funktionsdefinition stehen.

Auf das @param-Tag muss ein Typausdruck folgen.

Alternativ können Sie die Typen der Parameter auch inline angeben (siehe Funktion foo im Beispiel).

Beispiel:

/**
 * Queries a Baz for items.
 * @param {number} groupNum Subgroup id to query.
 * @param {string|number|null} term An itemName,
 *     or itemId, or null to search everything.
 */
goog.Baz.prototype.query = function(groupNum, term) {
  ...
};

function foo(/** number */ a, /** number */ b) {
  return a - b + 1;
}
Für Parameter, die ein Destrukturierungsmuster sind, können Sie nach der Typannotation einen beliebigen Namen verwenden, der eine gültige JS-Kennzeichnung ist.
/**
 * @param {{name: string, age: number}} person
 */
function logPerson({name, age}) {
  console.log(`${name} is ${age} years old`);
}
@private

Kennzeichnet ein Mitglied als privat. Nur Code in derselben Datei kann auf globale Variablen und Funktionen zugreifen, die mit @private gekennzeichnet sind. Konstruktoren, die mit @private gekennzeichnet sind, können nur durch Code in derselben Datei und durch ihre statischen und Instanzmember instanziiert werden.

Auf die öffentlichen statischen Eigenschaften von Konstruktoren, die mit @private gekennzeichnet sind, kann ebenfalls überall zugegriffen werden. Der Operator instanceof kann immer auf @private-Elemente zugreifen.

Beispiel:

/**
 * Handlers that are listening to this logger.
 * @private {Array<Function>}
 */
this.handlers_ = [];
@protected

Gibt an, dass ein Mitglied oder eine Eigenschaft geschützt ist.

Eine mit @protected gekennzeichnete Property ist für folgende Nutzer zugänglich:

  • Der gesamte Code befindet sich in derselben Datei.
  • statische Methoden und Instanzmethoden einer beliebigen Unterklasse der Klasse, für die die Property definiert ist.

Beispiel:

/**
 * Sets the component's root element to the given element.
 * Considered protected and final.
 * @param {Element} element Root element for the component.
 * @protected
 */
goog.ui.Component.prototype.setElementInternal = function(element) {
  // ...
};
@record

Markiert eine Funktion als strukturelle Schnittstelle. Eine strukturelle Schnittstelle ähnelt einer nominellen @interface, ermöglicht jedoch implizite Implementierungen. Das bedeutet, dass jede Klasse, die die Methoden und Eigenschaften enthält, die im Prototyp der strukturellen Schnittstelle definiert sind, die strukturelle Schnittstelle implementiert, unabhängig davon, ob das @implements-Tag verwendet wird. Datensatztypen und Objektliterale implementieren auch implizit eine strukturelle Schnittstelle, wenn sie die erforderlichen Eigenschaften enthalten.

Beispiel:

/**
 * Anything with a draw() method.
 * @record
 */
function Drawable() {};
Drawable.prototype.draw = function() {};

/**
 * A polygon.
 * @param {!Drawable} x
 */
function render(x) { x.draw(); };

var o = { draw() { /* ... */ } };
render(o);
@return

Gibt die Rückgabetypen von Methoden- und Funktionsdefinitionen an. Auf das @return-Tag muss ein Typausdruck folgen.

Alternativ können Sie den Rückgabetyp inline annotieren (siehe Funktion foo im Beispiel).

Wenn eine Funktion, die nicht in Externs enthalten ist, keinen Rückgabewert hat, können Sie das @return-Tag weglassen. Der Compiler geht dann davon aus, dass die Funktion undefined zurückgibt.

Beispiel:

/**
 * Returns the ID of the last item.
 * @return {string} The hex ID.
 */
goog.Baz.prototype.getLastId = function() {
  ...
  return id;
};

function /** number */ foo(x) { return x - 1; }
@struct

@struct wird verwendet, um Objekte mit einer festen Anzahl von Attributen zu erstellen. Wenn ein Konstruktor (Foo im Beispiel) mit @struct annotiert ist, können Sie nur die Punktnotation verwenden, um auf die Eigenschaften von Foo-Objekten zuzugreifen, nicht die Klammernotation. Außerdem können Sie einer Foo-Instanz nach der Erstellung keine Property mehr hinzufügen. Die Anmerkung kann auch direkt für Objektliterale verwendet werden.

Beispiel:

/**
 * @constructor
 * @struct
 */
function Foo(x) {
  this.x = x;
}
var obj1 = new Foo(123);
var someVar = obj1.x;  // OK
obj1.x = "qwerty";  // OK
obj1['x'] = "asdf";  // warning
obj1.y = 5;  // warning

var obj2 = /** @struct */ { x: 321 };
obj2['x'] = 123;  // warning
@template

Weitere Informationen finden Sie unter Generische Typen.

Beispiel:

/**
 * @param {T} t
 * @constructor
 * @template T
 */
Container = function(t) { ... };
@this

Gibt den Typ des Objekts an, auf das sich das Schlüsselwort this innerhalb einer Funktion bezieht. Auf das @this-Tag muss ein Typausdruck folgen.

Um Compilerwarnungen zu vermeiden, müssen Sie immer dann eine @this-Annotation verwenden, wenn this in einer Funktion vorkommt, die weder eine Prototypmethode noch eine als @constructor markierte Funktion ist.

Beispiel:

chat.RosterWidget.extern('getRosterElement',
    /**
     * Returns the roster widget element.
     * @this {Widget}
     * @return {Element}
     */
    function() {
      return this.getComponent().getElement();
    });
@throws

Wird verwendet, um die von einer Funktion ausgelösten Ausnahmen zu dokumentieren. Derzeit werden diese Informationen nicht vom Type Checker verwendet. Sie wird nur verwendet, um festzustellen, ob eine in einer Externs-Datei deklarierte Funktion Nebeneffekte hat.

Beispiel:

/**
 * @throws {DOMException}
 */
DOMApplicationCache.prototype.swapCache = function() { ... };
@type

Gibt den Typ einer Variablen, Eigenschaft oder eines Ausdrucks an. Auf das @type-Tag muss ein Typausdruck folgen.

Wenn Sie eine Variable oder einen Funktionsparameter deklarieren, können Sie die Typanmerkung inline schreiben und dabei {} und @type weglassen, wie im zweiten Beispiel. Diese Abkürzung ist nur möglich, wenn eine Variable oder ein Funktionsparameter deklariert wird. Wenn Sie den Typ später anpassen möchten, benötigen Sie eine Typumwandlung.

Beispiel:

/**
 * The message hex ID.
 * @type {string}
 */
var hexId = hexId;
var /** string */ name = 'Jamie';
function useSomething(/** (string|number|!Object) */ something) {
...
}
@typedef

Deklariert einen Alias für einen komplexeren Typ. Derzeit können Typdefinitionen nur auf der obersten Ebene und nicht innerhalb von Funktionen definiert werden. Wir haben diese Einschränkung in der neuen Typinferenz behoben.

Beispiel:

/** @typedef {(string|number)} */
goog.NumberLike;

/** @param {goog.NumberLike} x A number or a string. */
goog.readNumber = function(x) {
  ...
}
@unrestricted

Gibt an, dass eine Klasse weder vom Typ @struct noch vom Typ @dict ist. Dies ist die Standardeinstellung. Sie müssen sie also in der Regel nicht explizit angeben, es sei denn, Sie verwenden das class-Schlüsselwort, mit dem standardmäßig @struct-Klassen erstellt werden.

Beispiel:

/**
 * @constructor
 * @unrestricted
 */
function Foo(x) {
  this.x = x;
}
var obj1 = new Foo(123);
var someVar = obj1.x;  // OK
obj1.x = "qwerty";  // OK
obj1['x'] = "asdf";  // OK
obj1.y = 5;  // OK

Typausdrücke

Mit einem Typausdruck können Sie den Datentyp einer beliebigen Variablen, Eigenschaft, eines beliebigen Ausdrucks oder Funktionsparameters angeben. Ein Typausdruck besteht aus geschweiften Klammern („{ }“), die eine Kombination der unten beschriebenen Typoperatoren enthalten.

Verwenden Sie einen Typausdruck mit dem Tag @param, um den Typ eines Funktionsparameters zu deklarieren. Verwenden Sie einen Typausdruck mit dem Tag @type, um den Typ einer Variablen, Eigenschaft oder eines Ausdrucks zu deklarieren.

Je mehr Typen Sie in Ihrem Code angeben, desto mehr Optimierungen kann der Compiler vornehmen und desto mehr Fehler kann er erkennen.

Der Compiler verwendet diese Anmerkungen, um Ihr Programm auf Typen zu prüfen. Der Closure Compiler kann nicht garantieren, dass er den Typ jedes Ausdrucks in Ihrem Programm ermitteln kann. Es wird versucht, die Verwendung von Variablen und die Typanmerkungen in ihren Deklarationen zu analysieren. Anschließend werden eine Reihe von Algorithmen zur Typinferenz verwendet, um den Typ möglichst vieler Ausdrücke zu ermitteln. Einige dieser Algorithmen sind einfach („Wenn x eine Zahl ist und wir y = x; sehen, dann ist y eine Zahl“). Einige sind indirekter („Wenn der erste Parameter von f als Callback dokumentiert ist, der eine Zahl annehmen muss, und wir f(function(x) { /** ... */ }); sehen, dann muss x eine Zahl sein“).

Name des Operators Syntaxbeispiele Beschreibung
Typname {boolean}
{Window}
{goog.ui.Menu}
Gibt den Namen eines Typs an.
App-Typ {Array<string>}
Ein Array von Strings.

{Object<string, number>}
Ein Objekt, in dem die Schlüssel Strings und die Werte Zahlen sind.

Parametrisiert einen Typ mit einer Reihe von Typargumenten. Ähnlich wie Java-Generics.
Typ „Union“ {(number|boolean)}
Eine Zahl oder ein boolescher Wert.

Beachten Sie die erforderlichen Klammern.
Gibt an, dass ein Wert entweder Typ A oder Typ B haben kann.
Datensatztyp {{myNum: number, myObject}}
Ein anonymer Typ mit einem Attribut namens myNum, das einen Wert vom Typ number hat, und einem Attribut namens myObject, das einen Wert eines beliebigen Typs hat.

Gibt an, dass der Wert die angegebenen Elemente mit Werten der angegebenen Typen hat.

Geschweifte Klammern sind Teil der Typsyntax. Um beispielsweise eine Array von Objekten mit dem Attribut length anzugeben, können Sie
Array<{length}> schreiben. Im Beispiel links geben die äußeren geschweiften Klammern an, dass es sich um einen Typausdruck handelt, und die inneren geschweiften Klammern geben an, dass es sich um einen Datensatztyp handelt.

Typ mit zulässigen Nullwerten {?number}
Eine Zahl oder null.

Gibt an, dass ein Wert vom Typ A oder null ist.

Alle Objekttypen sind standardmäßig nullable, unabhängig davon, ob sie mit dem Operator „Nullable“ deklariert werden. Ein Objekttyp ist alles außer einer Funktion, einem String, einer Zahl oder einem booleschen Wert. Verwenden Sie den Operator Non-nullable, um einen Objekttyp als nicht nullfähig festzulegen.

Nicht nullable-Typ {!Object}
Ein Objekt, aber nie der Wert null.

Gibt an, dass ein Wert vom Typ A und nicht null ist.

Funktionen und alle Werttypen (boolesch, Zahl und String) sind standardmäßig nicht nullable, unabhängig davon, ob sie mit dem Operator „Non-nullable“ deklariert werden. Verwenden Sie den Operator Nullable, um einen Wert oder Funktionstyp als „nullable“ festzulegen.

Funktionstyp {function(string, boolean)}
Eine Funktion, die zwei Parameter (einen String und einen booleschen Wert) verwendet und einen unbekannten Rückgabewert hat.
Gibt eine Funktion und die Typen der Parameter der Funktion an.
Rückgabetyp der Funktion {function(): number}
Eine Funktion, die keine Parameter verwendet und eine Zahl zurückgibt.
Gibt den Typ des Rückgabewerts einer Funktion an.
Funktion this Typ {function(this:goog.ui.Menu, string)}
Eine Funktion, die einen Parameter (einen String) verwendet und im Kontext von goog.ui.Menu ausgeführt wird.
Gibt den Typ des Werts von this innerhalb der Funktion an.
Funktion new Typ {function(new:goog.ui.Menu, string)}
Eine Funktion, die einen Parameter (einen String) akzeptiert und eine neue Instanz von goog.ui.Menu erstellt, wenn sie mit dem Keyword „new“ aufgerufen wird.
Gibt den konstruierten Typ eines Konstruktors an.
Variable Parameter {function(string, ...number): number}
Eine Funktion, die einen Parameter (einen String) und dann eine variable Anzahl von Parametern verwendet, die Zahlen sein müssen.
Gibt an, dass ein Funktionstyp eine variable Anzahl von Parametern akzeptiert, und gibt einen Typ für die variablen Parameter an.
Variablenparameter (in @param-Hinweisen) @param {...number} var_args
Eine variable Anzahl von Parametern für eine annotierte Funktion.
Gibt an, dass die annotierte Funktion eine variable Anzahl von Parametern akzeptiert, und gibt einen Typ für die variablen Parameter an.
Optionaler Parameter in einer @param-Anmerkung @param {number=} opt_argument
Ein optionaler Parameter vom Typ number.

Gibt an, dass das durch eine @param-Annotation beschriebene Argument optional ist. Bei einem Funktionsaufruf kann ein optionales Argument weggelassen werden. Ein optionaler Parameter darf in der Parameterliste nicht vor einem nicht optionalen Parameter stehen.

Wenn bei einem Methodenaufruf ein optionaler Parameter ausgelassen wird, hat das Argument den Wert undefined. Wenn der Wert des Parameters also in einem Klassenattribut gespeichert wird, muss die Typdeklaration dieses Attributs einen möglichen Wert von undefined enthalten, wie im folgenden Beispiel:

/**
 * Some class, initialized with an optional value.
 * @param {Object=} opt_value Some value (optional).
 * @constructor
 */
function MyClass(opt_value) {
  /**
   * Some value.
   * @type {Object|undefined}
   */
  this.myValue = opt_value;
}
Optionales Argument in einem Funktionstyp {function(?string=, number=)}
Eine Funktion, die einen optionalen, auf null setzbaren String und eine optionale Zahl als Argumente akzeptiert.
Gibt an, dass ein Argument in einem Funktionstyp optional ist. Ein optionales Argument kann beim Funktionsaufruf weggelassen werden. Ein optionales Argument darf in der Argumentliste nicht vor einem nicht optionalen Argument stehen.
Der Typ „ALL“ {*} Gibt an, dass die Variable einen beliebigen Typ annehmen kann.
Der Typ „UNKNOWN“ {?} Gibt an, dass die Variable einen beliebigen Typ annehmen kann und der Compiler keine Typüberprüfung für die Verwendung der Variablen durchführen soll.

Typumwandlung

Verwenden Sie die folgende Syntax, um einen Wert in einen bestimmten Typ umzuwandeln:

/** @type {!MyType} */ (valueExpression)
Die Klammern um den Ausdruck sind immer erforderlich.

Generische Typen

Ähnlich wie Java unterstützt der Closure Compiler generische Typen, Funktionen und Methoden. Generics arbeiten mit Objekten verschiedener Typen und bewahren gleichzeitig die Typsicherheit zur Kompilierzeit.

Sie können Generics verwenden, um verallgemeinerte Sammlungen zu implementieren, die Verweise auf Objekte eines bestimmten Typs enthalten, und verallgemeinerte Algorithmen, die für Objekte eines bestimmten Typs ausgeführt werden.

Generischen Typ deklarieren

Ein Typ kann generisch gemacht werden, indem dem Konstruktor des Typs (für Klassen) oder der Schnittstellendeklaration (für Schnittstellen) eine @template-Annotation hinzugefügt wird. Beispiel:

/**
 * @constructor
 * @template T
 */
Foo = function() { ... };

Die Annotation @template T gibt an, dass Foo ein generischer Typ mit einem Vorlagentyp, T, ist. Der Vorlagentyp T kann als Typ im Rahmen der Definition von Foo verwendet werden. Beispiel:

/** @return {T} */
Foo.prototype.get = function() { ... };

/** @param {T} t */
Foo.prototype.set = function(t) { ... };

Die Methode get gibt ein Objekt des Typs T zurück und die Methode set akzeptiert nur Objekte des Typs T.

Generischen Typ instanziieren

Wenn wir das obige Beispiel wiederverwenden, kann eine Vorlageninstanz von Foo auf verschiedene Arten erstellt werden:

/** @type {!Foo<string>} */ var foo = new Foo();
var foo = /** @type {!Foo<string>} */ (new Foo());

Mit beiden oben genannten Konstruktoranweisungen wird eine Foo-Instanz erstellt, deren Vorlagentyp T string ist. Der Compiler erzwingt, dass Aufrufe der Methoden von foo und Zugriffe auf die Eigenschaften von foo den Typ der Vorlage berücksichtigen. Beispiel:

foo.set("hello");  // OK.
foo.set(3);        // Error - expected a string, found a number.
var x = foo.get(); // x is a string.

Instanzen können auch implizit durch ihre Konstruktorargumente typisiert werden. Sehen Sie sich einen anderen generischen Typ an: Bar

/**
 * @param {T} t
 * @constructor
 * @template T
 */
Bar = function(t) { ... };
var bar = new Bar("hello"); // bar is a Bar<string>

Der Typ des Arguments für den Konstruktor Bar wird als string abgeleitet. Daher wird die erstellte Instanz bar als Bar<string> abgeleitet.

Mehrere Vorlagentypen

Ein generischer Typ kann beliebig viele Vorlagentypen haben. Die folgende Kartenklasse hat zwei Vorlagentypen:

/**
 * @constructor
 * @template Key, Val
 */
MyMap = function() { ... };

Alle Vorlagentypen für einen generischen Typ müssen in derselben @template-Annotation als durch Kommas getrennte Liste angegeben werden. Die Reihenfolge der Namen der Vorlagentypen ist wichtig, da bei Anmerkungen für Vorlagentypen die Reihenfolge verwendet wird, um Vorlagentypen mit den Werten zu verknüpfen. Beispiel:

/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.

Invarianz generischer Typen

Der Closure Compiler erzwingt die invariante generische Typisierung. Wenn in einem Kontext der Typ Foo<X> erwartet wird, können Sie also nicht den Typ Foo<Y> übergeben, wenn X und Y unterschiedliche Typen sind, auch wenn einer ein Untertyp des anderen ist. Beispiel:

/**
 * @constructor
 */
X = function() { ... };

/**
 * @extends {X}
 * @constructor
 */
Y = function() { ... };

/** @type {Foo<X>} */ var fooX;
/** @type {Foo<Y>} */ var fooY;

fooX = fooY; // Error
fooY = fooX; // Error

/** @param {Foo<Y>} fooY */
takesFooY = function(fooY) { ... };

takesFooY(fooY); // OK.
takesFooY(fooX); // Error

Vererbung generischer Typen

Generische Typen können übernommen werden und ihre Vorlagentypen können entweder festgelegt oder an den übernehmenden Typ weitergegeben werden. Hier ein Beispiel für einen untergeordneten Typ, der den Vorlagentyp seines übergeordneten Typs korrigiert:

/**
 * @constructor
 * @template T
 */
A = function() { ... };

/** @param {T} t */
A.prototype.method = function(t) { ... };

/**
 * @constructor
 * @extends {A<string>}
 */
B = function() { ... };

Durch die Erweiterung von A<string> hat B eine Methode method, die einen Parameter vom Typ string akzeptiert.

Hier sehen Sie ein Beispiel für einen untergeordneten Typ, der den Vorlagentyp seines übergeordneten Typs weitergibt:

/**
 * @constructor
 * @template U
 * @extends {A<U>}
 */
C = function() { ... };

Durch die Erweiterung von A<U> haben Vorlageninstanzen von C eine Methode method, die einen Parameter des Vorlagentyps U akzeptiert.

Schnittstellen können auf ähnliche Weise implementiert und erweitert werden, aber ein einzelner Typ kann dieselbe Schnittstelle nicht mehrmals mit verschiedenen Vorlagentypen implementieren. Beispiel:

/**
 * @interface
 * @template T
 */
Foo = function() {};

/** @return {T} */
Foo.prototype.get = function() {};

/**
 * @constructor
 * @implements {Foo<string>}
 * @implements {Foo<number>}
 */
FooImpl = function() { ... }; // Error - implements the same interface twice

Generische Funktionen und Methoden

Ähnlich wie bei generischen Typen können Funktionen und Methoden durch Hinzufügen einer @template-Annotation zu ihrer Definition generisch gemacht werden. Beispiel:

/**
 * @param {T} a
 * @return {T}
 * @template T
 */
identity = function(a) { return a; };

/** @type {string} */ var msg = identity("hello") + identity("world"); // OK
/** @type {number} */ var sum = identity(2) + identity(2); // OK
/** @type {number} */ var sum = identity(2) + identity("2"); // Type mismatch