type式

type 式とは

type 式とは、

@type {type_expression}

の type_expression にあたる部分のことです。

関数の引数の型や、戻り値の型について記述するときにも使いますね。

さて、Jsdoc や ClosureCompiler ではかなり複雑な type 式の解析可能です。たとえば、

  • {function(this:goog.ui.Menu, string)} (実在します)

  • {Array|NodeList|Arguments|{length: number}} (実在します)

1つめは、goog.ui.Menu クラスのインスタンスが this に束縛されていて、かつ第一引数に文字列をうけとることができ、戻り値を返さない関数、という type 式です。2つめは、配列、 NodeList オブジェクト、関数の引数オブジェクト、 length プロパティが数値である何らかのオブジェクトのいずれか、という type 式です。濃いですね。

たとえば、 String#replace(arg1, arg2) の 引数 をあらわす type 式を考えてみてください。

arg1 は文字列か正規表現オブジェクトですよね。なので、“AかBのどちらか” をあらわす|を使います。

@param {string|RegExp} 変換される前の文字列デース。

arg2 は、文字列か関数です。ということは、

@param {string|Function} 変換される前の文字列デース。

ですね。関数についてはもっと詳しく書くことができます。function(引数1, 引数2): 戻り値 というように引数・戻り値の型を指定できるのです。第一引数がマッチ全体の文字列、以降は正規表現内の括弧に対応するマッチ文字列が続き、最後の二つがオフセット位置の数値、全体の文字列、戻り値は文字列ということは、

@param {string|function(string, ...string, number, string): string} 置き換える文字列または文字列を返す関数デース。

というふうに書くことができます。

type 式の限界を試してみたい方は、jsdoctypeparser で簡単に試すことができますよ!!!(宣伝)

type 式の書き方

A という型 ⇒ {A}

A という型は、そのまま書けばOKです。

ただ、string、number、booleanについては、プリミティブな値であることを示すために小文字から始まるのが慣習です。

(プリミティブとかイミワカンネという方は、是非 JavaScript の暗部をのぞいてみてください)

A か B のどちらか ⇒ {A|B}

A か B か C か ... のどれか、という場合には、{A|B|C...(|区切りで続ける)} と書きます。

A や Bには、型名・ジェネリック型・関数型・レコード型が指定できます。

なんでもこい ⇒ {*}

どんな型でもよい場合は {*} と書きます。

undefinedかもしれない A ⇒ {A=} または {A|undefined}

引数などで A が省略可能な場合は {A=} と書きます。もし、A か B か undefined という場合には 2 通りの書き方({A|B|undefined}、{A|B=})がありますが、前者がgoodです。理由は、=がBにかかるのか結合式にかかるのかが分かりづらいからです(どちらも意味することは同じですが)。

nullかもしれない A ⇒ {?A} または {A|null} (?は後付け{A?} でもいけるが非推奨。やめましょう)

引数がnullかもしれない場合は、{?A} のように書きます。もし、A か B か null という場合には 2 通りの書き方({A|B|null}、{?A|B})がありますが、前者がgoodです。

nullじゃない A ⇒ {!A} (!は後付け{A!}でもいけますが非推奨。やめましょう)

戻り値が null じゃないことを明示したい場合は、{!A} というように書きます。

関数が配列などを返す場合に、絶対に null にはならんぞ!という意思表示をするときにつかいます。

これがあると、安心して戻り値のプロパティにアクセスできるようになります(nullやundefinedのプロパティアクセスはエラーになる)。

ジェネリクスみたいに書きたい ⇒ {Generic.<Val1, Val2>}

ジェネリクス(総称型。要素の型が決められた配列など)を明示したい場合には、{Generic.<Val1, Val2>} のように書きます。

Generic の部分には型名を、Valの部分には type 式が指定できます。

また、配列であれば String[] という、古い Jsdoc の書き方も使うことができます(オススメはしません)。

関数の引数の型 A・Bを明示したい ⇒ {function(A, B)}

関数の引数を明示したい場合には、{function(A, B, C, D)}というように書きます。

type 式が指定できます。

関数の戻り値を明示したい ⇒ {function(): A}

関数の引数を明示したい場合には、{function(): A}というように書きます。

type 式が指定できます。

関数のthisが示すものを明示したい ⇒ {function(this: ThisObj)}

関数内の this があらわすものを明示したい場合には {function(this: ThisObj)} というように書きます。

引数がある場合は、カンマ区切りで続けて書きます。

this には型名が指定できます。

関数がコンストラクタだと明示したい ⇒ {function(new: NewObj)}

関数がコンストラクタだと明示したい場合には、{function(new: NewObj} というように書きます。

new には型名が指定できます。

オブジェクトの持つプロパティを明示したい ⇒ {{key1: Val1, key2: Val2}}

引数をまとめてオブジェクトとして指定できる場合などには、{{key1: Val1, key2: Val2}} のように書きます。

type式が指定できます。

もっと知りたい?

これらの仕様は ECMAScript 4 203 から 252 あたりに載ってます。

あるいは、jsdoc おじさん (~♥~) に聞いてください。