注: このページの内容は古くなっています。完全なリストは 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 Compiler は、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} */
|
@extends
|
クラスまたはインターフェースが別のクラスから継承されることを示します。
注:
継承の実装例については、Closure ライブラリの関数 次に例を示します。 /** * 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; } /** * @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
|
メソッドと関数定義の戻り値の型を指定します。
または、戻り値の型をインラインでアノテーションすることもできます(例の関数
externs にない関数に戻り値がない場合は、 次に例を示します。 /** * 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
|
関数によってスローされる例外を文書化するために使用されます。現在、型チェッカーはこの情報を使用していません。これは、externs ファイルで宣言された関数に副作用があるかどうかを判断するためにのみ使用されます。 次に例を示します。 /** * @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}
|
型の名前を指定します。 |
Type Application |
{Array<string>} 文字列の配列。
|
型引数のセットを使用して型をパラメータ化します。Java のジェネリクスに似ています。 |
型 Union |
{(number|boolean)} 数値またはブール値。 括弧は必須です。 |
値が型 A または型 B の可能性があることを示します。 |
レコードタイプ |
{{myNum: number, myObject}}
値の型が number の myNum という名前のプロパティと、値の型が任意の型の myObject という名前のプロパティの両方を持つ匿名型。 |
値に、指定された型の値を持つ指定されたメンバーがあることを示します。 中かっこは型構文の一部です。たとえば、 |
null 許容型 |
{?number} 数字または null 。
|
値が A 型または すべてのオブジェクト型は、Nullable 演算子で宣言されているかどうかに関係なく、デフォルトで null 許容です。オブジェクト型は、関数、文字列、数値、ブール値以外のものとして定義されます。オブジェクト型を null 許容型にするには、null 許容型演算子を使用します。 |
null 許容でない型 |
{!Object} オブジェクト。ただし、 null 値は使用されません。 |
値が型 A で null ではないことを示します。 関数とすべての値の型(ブール値、数値、文字列)は、Non-nullable 演算子で宣言されているかどうかに関係なく、デフォルトで 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=)} 省略可能な null 許容文字列と省略可能な数値を引数として受け取る関数。 |
関数型の引数が省略可能であることを示します。省略可能な引数は、関数呼び出しから省略できます。省略可能な引数は、引数リストで省略可能でない引数の前に置くことはできません。 |
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
が異なる型であれば、一方が他方のサブタイプであっても、型 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