注: このページは最新ではありません。詳細なリストについては、https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler をご覧ください。
概要
Closure Compiler は JavaScript 変数のデータ型情報を使用して、最適化と警告を強化できます。ただし、JavaScript には型を宣言する手段がありません。
JavaScript には変数の型を宣言する構文がないため、コード内でコメントを使用してデータ型を指定する必要があります。
Closure Compiler 型の言語は JSDoc ドキュメント生成ツールで使用されるアノテーションから取得されますが、その後変更されました。JSDoc がサポートしていないアノテーションと、その逆のアノテーションがいくつか含まれています。このドキュメントでは、Closure Compiler が認識できるアノテーションと型式のセットについて説明します。
JSDoc タグ
Closure コンパイラは JSDoc タグで型情報を検索します。下記のリファレンス テーブルに記載されている JSDoc タグを使用して、コンパイラでコードを最適化し、型エラーなどの間違いがないかどうかを確認してください。
この表には、Closure Compiler の動作に影響するタグのみが含まれています。その他の JSDoc タグの詳細については、JSDoc Toolkit ドキュメントをご覧ください。
タグ | 説明 |
---|---|
@abstract
|
メソッドを抽象としてマークします。メソッドを
/** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
変数を読み取り専用としてマークします。コンパイラは、 型宣言は省略可能です。
/** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
関数をコンストラクタとしてマークします。コンパイラは、 例: /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
コンパイラがコンパイル時にオーバーライドできる定数を示します。
左側の例では、--define='ENABLE_DEBUG=false' フラグをコンパイラに渡して、ENABLE_DEBUG の値を false に変更できます。
定義済みの定数のタイプは、数値、文字列、ブール値のいずれかです。定義はグローバル スコープでのみ許可されます。
例: /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
関数、メソッド、プロパティをマークします。これにより、使用すべきでないコンパイラ警告が生成されます。 例: /** * 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
|
例: /** * @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
|
列挙型の型を指定します。列挙型は、関連する一連の定数をプロパティとして構成するオブジェクトです。 列挙型の型ラベルは、列挙型の各プロパティに適用されます。たとえば、列挙型の型が 例: /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
このコードの場合 /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
コンパイラが goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); これにより、シンボルがコンパイルされていないコードにエクスポートされます。 /** * @export * @type {SomeType} */の省略形として /** @export {SomeType} */ を作成できます。
|
@extends
|
クラスまたはインターフェースを別のクラスから継承するマークを付けます。
注:
継承の実装例については、Closure Library の関数 例: /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
このクラスを拡張できないことを示します。 メソッドについて、そのメソッドをオーバーライドできるサブクラスがないことを示します。 例: /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
コンストラクタに 例: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
このアノテーションは externs プロパティ宣言にのみ表示できます。プロパティには宣言された型がありますが、警告なしで任意の型を割り当てることができます。プロパティにアクセスすると、宣言された型の値が返されます。たとえば、 /** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
サブクラスのメソッドまたはプロパティがスーパークラスのメソッドまたはプロパティを意図的に非表示にし、まったく同じドキュメントを持っていることを示します。 例: /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
関数をインターフェースとしてマークする。インターフェースには、型に必要なメンバーを指定します。インターフェースを実装するクラスは、そのインターフェースのプロトタイプで定義されているすべてのメソッドとプロパティを実装する必要があります。詳細については、
コンパイラは、インターフェースがインスタンス化されていないことを確認します。 例: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
オブジェクト リテラルのキーは、他のオブジェクトのプロパティとして扱う必要があります。このアノテーションは、オブジェクト リテラルにのみ表示されます。
中かっこ内の名前は、他のアノテーションのような型名ではありません。オブジェクト名です。このプロパティは、プロパティが貸し出されるオブジェクトの名前を指定します。たとえば、 このアノテーションについて詳しくは、JSDoc Toolkit ドキュメントをご覧ください。 例: goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license または @preserve |
マークされたファイルのコンパイル済みコードの前に、関連するコメントを挿入するようにコンパイラに指示します。このアノテーションを使用すると、コンパイル時の変更後も重要な通知(法的ライセンスや著作権テキストなど)を通知できます。改行は保持されます。 例: /** * @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
|
コンパイラが変数に折りたたむべきではないプロパティを示します。 例: /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
宣言された外部関数の呼び出しに副作用がないことを示します。このアノテーションを使用すると、戻り値が使用されていない場合、コンパイラは関数の呼び出しを削除できます。アノテーションは 例: /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
サブクラスのメソッドまたはプロパティがスーパークラスのメソッドまたはプロパティを意図的に非表示にすることを示します。他のアノテーションが含まれていない場合、メソッドまたはプロパティは自動的にスーパークラスからアノテーションを継承します。 例: /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
メンバーまたはプロパティを非公開としてマークします。同じディレクトリ内のコードのみが、
パブリック コンストラクタには、 例: /** * 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
|
関数の引数のタイプを指定するために、メソッド、関数、コンストラクタの定義で使用されます。
または、パラメータの型をインラインでアノテーションすることもできます(この例では 例: /** * 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; }破棄パターンのパラメータの場合、型 アノテーションの後に、有効な JS 識別子の任意の名前を使用できます。 /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
メンバーを非公開に設定する。同じファイル内のコードのみが、
例: /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
メンバーまたはプロパティが保護されることを示します。
例: /** * 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
|
関数を構造インターフェースとしてマークします。構造インターフェースは名詞 例: /** * 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
|
メソッドと関数の定義の戻り値の型を指定します。
あるいは、戻り値の型にアノテーションを付けることもできます(この例の関数
外部にない関数に戻り値がない場合、 例: /** * 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
|
例: /** * @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
|
汎用型をご覧ください。 例: /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
関数内で、キーワード
コンパイラ警告を防ぐには、プロトタイプ メソッドでも 例: chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
関数からスローされた例外を文書化するために使用されます。 タイプ チェッカーは現在、この情報を使用しません。 これは、外部ファイルで宣言された関数に副作用があるかどうかを判断するためにのみ使用されます。 例: /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
変数、プロパティ、式のタイプを示します。 変数または関数のパラメータを宣言する場合、2 番目の例のように、 例: /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
より複雑な型のエイリアスを宣言します。現在、typedef は関数内ではなく、トップレベルでのみ定義できます。新しい型推論でこの制限を修正しました。 例: /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
クラスが 例: /** * @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 |
型式
変数、プロパティ、式、関数パラメータのデータ型を型式で指定できます。型式は、以下で説明する型演算子の組み合わせを含む中かっこ(「 }」)で構成されます。
関数パラメータの型を宣言するには、@param
タグで型式を使用します。変数、プロパティ、または式のタイプを宣言するには、@type
タグで型式を使用します。
コード内で指定するタイプが多いほど、コンパイラが最適化できる箇所が増え、検出できるミスも増えます。
コンパイラは、これらのアノテーションを使用してプログラムの型チェックを行います。
なお、Closure Compiler では、プログラムのすべての式のタイプを認識できるようになるとは約束しません。ベスト プラクティスは、変数の使い方と、宣言に添付される型のアノテーションを確認することです。次に、いくつかの型推論アルゴリズムを使用して、可能な限り多くの式のタイプを計算します。これらのアルゴリズムの一部は簡単です(「x が数値で、y = x;
の場合は y は数値です」)。一部は間接的です(「f の最初のパラメータをコールバックとして文書化する必要があり、数値を受け取る必要があり、f(function(x) { /** ... */ });
が表示されている場合、x は数字でなければなりません」)。
演算子名 | 構文の例 | 説明 |
---|---|---|
型名 |
{boolean} {Window} {goog.ui.Menu}
|
タイプの名前を指定します。 |
タイプ: アプリケーション |
{Array<string>} 文字列の配列。
|
型の引数のセットを使用して型をパラメータ化します。Java ジェネリックに似ています。 |
タイプ: ユニオン |
{(number|boolean)} 数値またはブール値。 かっこは必須です。 |
値がタイプ A またはタイプ B を持つ可能性があることを示します。 |
レコードタイプ |
{{myNum: number, myObject}}
number 型の値を持つ myNum というプロパティと、任意の型を持つ myObject というプロパティの両方を持つ匿名型。 |
値に、指定された型の値を持つ指定されたメンバーがあることを示します。 中かっこは型構文の一部です。たとえば、 |
null 値許容型 |
{?number} 数値または null 。
|
値がタイプ A または Nullable 演算子を使用して宣言しているかどうかにかかわらず、デフォルトですべてのオブジェクト型は null 値許容です。オブジェクト型は、関数、文字列、数値、ブール値以外のすべてとして定義されます。オブジェクト タイプを null 値非許容にするには、非 null 値許容演算子を使用します。 |
null 値非許容型 |
{!Object} null オブジェクトではなく、オブジェクト。 |
値が null ではなくタイプ A であることを示します。 関数とすべての値の型(ブール値、数値、文字列)は、null 値非許容の演算子で宣言されているかどうかにかかわらず、デフォルトで null 値非許容型です。値または関数型を null 値許容型にするには、Nullable 演算子を使用します。 |
関数型 |
{function(string, boolean)} 2 つのパラメータ(文字列とブール値)を受け取り、不明な戻り値を持つ関数。 |
関数と関数のパラメータの型を指定します。 |
関数の戻り値の型 |
{function(): number} パラメータを受け取らず数値を返す関数。 |
関数の戻り値の型を指定します。 |
関数 this 型 |
{function(this:goog.ui.Menu, string)} 1 つのパラメータ(文字列)を受け取り、goog.ui.Menu のコンテキストで実行する関数。 |
関数内の this の値の型を指定します。 |
関数 new 型 |
{function(new:goog.ui.Menu, string)} 1 つのパラメータ(文字列)を受け取り、new キーワードで呼び出されたときに goog.ui.Menu の新しいインスタンスを作成する関数。 |
コンストラクタの指定された型を指定します。 |
変数パラメータ |
{function(string, ...number): number} 1 つのパラメータ(文字列)を受け取り、その後に数値である可変数のパラメータを取る関数。 |
関数型が可変パラメータを受け取り、変数パラメータの型を指定することを示します。 |
変数パラメータ(@param アノテーション内) |
@param {...number} var_args アノテーション付き関数への可変パラメータの数。 |
アノテーション付き関数が可変パラメータを受け入れ、変数パラメータの型を指定します。 |
@param アノテーション内のオプション パラメータ |
@param {number=} opt_argument number タイプのオプションのパラメータ。 |
メソッド呼び出しで省略可能なパラメータを省略した場合、その引数の値は /** * 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; } |
関数型の省略可能な引数 |
{function(?string=, number=)} 1 つの省略可能な null 値許容文字列と 1 つのオプションの数字を引数として受け取る関数。 |
関数型の引数が省略可能であることを示します。関数呼び出しからオプションの引数を省略できます。省略可能な引数を、引数リストの引数以外の引数の前に置くことはできません。 |
ALL 型 | {*} |
変数が任意の型を取ることを示します。 |
UNKNOWN 型 | {?} |
変数は任意の型を取ることができ、コンパイラは変数の型チェックを行わないことを示します。 |
型キャスト
特定の型に値をキャストするには、この構文を使用します。
/** @type {!MyType} */ (valueExpression)式を囲むかっこは常に必要です。
汎用型
Java と同様に、Closure Compiler は汎用型、関数、メソッドをサポートします。ジェネリックは、コンパイル時の型の安全性を維持しながら、さまざまな型のオブジェクトで動作します。
ジェネリックを使用すると、特定の型のオブジェクトへの参照を保持する一般化されたコレクションと、特定の型のオブジェクトで動作する一般化されたアルゴリズムを実装できます。
汎用型を宣言する
型を汎用化するには、型のアノテーション(クラスの場合)またはインターフェースの宣言(インターフェースの場合)に @template
アノテーションを追加します。次に例を示します。
/** * @constructor * @template T */ Foo = function() { ... };
アノテーション @template T
は、Foo
が 1 つのテンプレート タイプ(T
)を持つ汎用型であることを示します。テンプレート タイプ T
は、Foo
の定義の範囲内で使用できます。次に例を示します。
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
get
メソッドは T
型のオブジェクトを返し、メソッド set
は T
型のオブジェクトのみを受け入れます。
汎用型のインスタンス化
上記の例を再利用すると、Foo
のテンプレート インスタンスをいくつかの方法で作成できます。
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
上記のコンストラクタ ステートメントはどちらも、テンプレート タイプ T
が string
の Foo
インスタンスを作成します。コンパイラは、foo
のメソッドの呼び出しを強制し、foo
のプロパティにアクセスして、テンプレート化された型を尊重します。次に例を示します。
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
インスタンスはコンストラクタ引数によって暗黙的に入力することもできます。別の汎用タイプである Bar
について考えてみます。
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
Bar
コンストラクタの引数の型は string
として推定されます。その結果、作成されたインスタンス bar
は Bar<string>
として推定されます。
複数のテンプレート タイプ
ジェネリックには任意のタイプのテンプレートを指定できます。次のマップクラスには、2 つのテンプレート タイプがあります。
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
汎用型のテンプレート型はすべて、カンマ区切りのリストとして同じ @template
アノテーションで指定する必要があります。テンプレート タイプ名の順序は重要です。テンプレート タイプのアノテーションでは、この順序を使用してテンプレート タイプと値をペア設定します。次に例を示します。
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
汎用型の不変性
Closure Compiler では不変の汎用型が適用されます。つまり、コンテキストが Foo<X>
型を想定している場合、X
と Y
の型が互いに異なる場合でも、1 つの型 Foo<Y>
を渡すことはできません。次に例を示します。
/** * @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
汎用型の継承
汎用型は継承可能で、テンプレート型は継承型に固定または伝播できます。継承された型の例で、そのスーパータイプのテンプレート型を修正する例を次に示します。
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
A<string>
を拡張することで、B
には、string
型のパラメータを取るメソッド method
が含まれるようになります。
スーパータイプのテンプレート タイプを伝播する継承タイプの例を次に示します。
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
A<U>
を拡張することで、テンプレート化された C
のインスタンスには、テンプレート タイプ U
のパラメータを受け取るメソッド method
が含まれます。
インターフェースは同様の方法で実装と拡張が可能ですが、1 つの型が異なるテンプレート型を使用して同じインターフェースを複数回実装することはできません。次に例を示します。
/** * @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
汎用関数とメソッド
汎用型と同様に、関数とメソッドは、定義に @template
アノテーションを追加することで汎用化できます。次に例を示します。
/** * @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