Google JavaScript スタイルガイド - 日本語訳

JavaScriptのデータ型

最終更新:

aias-jsstyleguide2

- view
管理者のみ編集可
include_js plugin Error : このプラグインで利用できない命令または文字列が入っています。
JavaScriptのデータ型
JSDocへのデータ型の記述は、できるだけ具体的かつ正確に行ってください。我々のサポートする型のスタイルはEcmaScript 4 仕様に基づいています。

JavaScriptの型言語

ES4の提案にはJavaScriptのデータ型を定義する言語が含まれていました。この言語をJSDoc内で用い、関数パラメータや戻り値の型を表現します。

ES4提案の進展に伴い、その型言語も変化しています。Compilerは古い構文もサポートしていますが、現在それらは非推奨となっています。
構文名 構文 説明 非推奨の構文
Primitive Type JavaScriptに含まれる5種類のプリミティブ型: {null}, {undefined}, {boolean}, {number}, {string} シンプルな型名称
Instance Type {Object}
Objectのインスタンスもしくはnull

{Function}
Functonのインスタンスもしくはnull

{EventTarget}
EventTargetインタフェースを実装するコンストラクタのインスタンスもしくはnull
コンストラクタまたはインタフェースのインスタンスであることを表します。

コンストラクタ関数は@cpnstructorJSDocタグによって定義されます。インタフェース関数は@interfaceJSDocタグによって定義されます。

デフォルトで、Instance Typeはnullを許可します。このタイプはnullを許す唯一のものです。この表に含まれる他の構文はデフォルトでnullを許可しません。
Enum Type {goog.events.EventType}
goog.events.EventTypeの列挙値で初期化されたオブジェクトリテラルのプロパティのどれか
列挙型の変数はオブジェクトリテラルもしくは他の列挙型変数の別名で、@enumJSDocタグがアノテートされていなければなりません。このオブジェクトリテラルのプロパティが、列挙値の実体となります。列挙型の構文についてはこちらで定義されています。

注意:この型は、我々の型システムのうちES4仕様に含まれない数少ないもののひとつです。
Type Application {Array.<string>}
文字列の配列

{Object.<string, number>}
キーが文字列、値が数値のオブジェクト
型引数のセットを付記し、型をパラメータ化します。考え方はJavaのジェネリクスによく似ています。
Type Union {(number|boolean)}
数値または論理値
値の型がAまたはBであることを表します。

この型が最上位の式で使われる場合、丸括弧は省略しても構いません。しかしそうでない場合は、曖昧さを避けるために丸括弧を付けてください。
{number|boolean}
{function(): (number|boolean)}
{(number,boolean)}, {(number||boolean)}
Nullable Type {?number}
数値またはNULL。
Unionの省略形で、何らかの型もしくはnullであることを表します。この型は糖衣構文です。 {number?}
Non-nullable Type {!Object}
Object型ですが、nullは許されません。
この型がnullを許容しないことを表します。殆どの場合、デフォルトでnullを許すInstance Typeに対して使用されます。 {Object!}
Record Type {{myNum: number, myObject}}
型指定されたメンバを持つ無名オブジェクト
値が指定された型のメンバを持つオブジェクトであることを表します。左のケースでは、myNumは数値、myObjectはどの型でも取れるプロパティです。

波括弧は構文の一部であることに注意してください。例えばArraylengthというプロパティを持つオブジェクトの配列であることを示すには、Array.<{length}>のように書きます。
Function Type {function(string, boolean)}
2つの引数(文字列と論理値)を取り、戻り値が指定されていない関数。
関数を定義します。
Function Return Type {function(): number}
引数を取らず、数値を戻り値として返す関数。
関数の戻り値の型を定義します。
Function this Type {function(this:goog.ui.Menu, string)}
文字列の引数1つをとり、goog.ui.Menuのコンテキストで実行される関数。
関数のコンテキストの型を定義します。
Function new Type {function(new:goog.ui.Menu, string)}
文字列の引数を1つ取るコンストラクタ関数。'new'キーワードと共にコールされるときにはgoog.ui.Menuのインスタンスを生成します。
コンストラクタによって作成される型を定義します。
Variable arguments {function(string, ...[number]): number}
引数として文字列を1つと、可変個数の数値を取る関数。
関数に個数の変化する引数を定義します。
Variable arguments (in @param annotations) @param {...number} var_args
可変個数の引数を取るようアノテートされた関数。
可変個数の引数を受け取れるようアノテートされた関数を定義します。
Function optional arguments {function(?string=, number=)}
省略可能な、nullでもよい文字列型の引数と、省略可能な数値型の引数を取る関数。=は関数型の宣言の中でのみ使います。
関数の省略可能な引数を定義します。
Function optional arguments (in @param annotations) @param {number=} opt_argument
数値型の省略可能なパラメータ。
省略可能な引数を受け取れるようアノテートされた関数を定義します。
The ALL Type {*} その変数がどのような型でも取れることを表します。
The UNKNOWN Type {?} その変数がどのような型でも取れ、Compilerはそれを使った型チェックを行ってはならないことを表します。

JavaScriptで使えるデータ型

型名の例 値の例 説明
number 1
1.0
-5
1e5
Math.PI
Number new Number(true) Numberオブジェクト
string 'Hello'
"World"
String(42)
文字列値
String new String('Hello')
new String(42)
Stringオブジェクト
boolean true
false
Boolean(0)
論理値
Boolean new Boolean(true) Booleanオブジェクト
RegExp new RegExp('hello')
/world/g
Date new Date
new Date()
null null
undefined undefined
void function f() {
  return;
}
戻り値なし
Array ['foo', 0.3, null]
[]
型指定のない配列
Array.<number> [11, 22, 33] 数値の配列
Array.<Array.<string>> [['one', 'two', 'three'], ['foo', 'bar']] 文字列の配列の配列
Object {}
{foo: 'abc', bar: 123, baz: null}
Object.<string> {'foo': 'bar'} 文字列の値を持つオブジェクト
Object.<number, string> var obj = {};
obj[1] = 'bar';
キーが数値で値が文字列のオブジェクト。

JavaScriptではオブジェクトのキーは暗黙的に文字列に変換される点に注意してください。従ってobj['1'] == obj[1]です。また for...in ループの中でもキーは常に文字列です。しかしCompilerはオブジェクトのキーをインデックス化する際、その型を識別します。
Function function(x, y) {
  return x * y;
}
Functionオブジェクト
function(number, number): number function(x, y) {
  return x * y;
}
関数
SomeClass /** @constructor */
function SomeClass() {}

new SomeClass();
SomeInterface /** @interface */
function SomeInterface() {}

SomeInterface.prototype.draw = function() {};
project.MyClass /** @constructor */
project.MyClass = function () {}

new project.MyClass()
project.MyEnum /** @enum {string} */
project.MyEnum = {
  /** 青色 */
  BLUE: '#0000dd',
  /** 赤色 */
  RED: '#dd0000'
};
列挙型

列挙値に対するJSDocコメントは省略可能です。
Element document.createElement('div') DOM要素
Node document.body.firstChild DOMノード
HTMLInputElement htmlDocument.getElementsByTagName('input')[0] DOM要素の型を明示的に指定します。

型キャスト

ある式のデータ型を型チェック機能が正確に推測できないケースでは、型キャストコメントを利用できます。型キャストコメントには@typeアノテーションでデータ型を示し、式は丸括弧で括ります。丸括弧は必須です。
/** @type {number} */ (x)

そのパラメータ・プロパティは「Nullを許す」のか「省略できる」のか

JavaScriptは型に厳格でない言語なので、関数パラメータやクラスプロパティにおける「nullを許す」、「省略できる」、「undefined」の微妙な違いを理解しておくことは非常に重要です。

クラスとインタフェースのインスタンスはデフォルトでnullを許します。例として、以下の宣言をみてください:
/**
 * 何かのクラス、何らかの値で初期化されます。
 * @param {Object} value 何かの値。
 * @constructor
 */
function MyClass(value) {
  /**
   * 何かの値。
   * @type {Object}
   * @private
   */
  this.myValue_ = value;
}
上のコードはCompilerに対し、myValue_プロパティが値として持つのはオブジェクトかnullのどちらかだと伝えています。もし myValue_プロパティが決してnullとならないのなら、こう宣言されるべきです:
/**
 * 何かのクラス、nullでない何らかの値で初期化されます。
 * @param {!Object} value 何かの値。
 * @constructor
 */
function MyClass(value) {
  /**
   * 何かの値。
   * @type {!Object}
   * @private
   */
  this.myValue_ = value;
}
この場合、もしコードのどこかでMyClassがnull値で初期化されていることをCompilerが検出すると、Compilerから警告が発せられます。

省略されたパラメータはおそらくランタイムによってundefinedとして扱われます。それらがオブジェクトのプロパティに代入されるのであれば、プロパティもまたそれに応じて適切に宣言されていなければなりません:
/**
 * 何かのクラス、省略可能な何らかの値で初期化されます。
 * @param {Object=} opt_value 何かの値(省略可)。
 * @constructor
 */
function MyClass(value) {
  /**
   * 何かの値。
   * @type {Object|undefined}
   * @private
   */
  this.myValue_ = value;
}
上のコードはCompilerに対し、myValue_の値はオブジェクトかnull、あるいはundefinedのままであると伝えています。

省略可能なパラメータopt_valueの型が{Object=}と宣言されており、{Object|undefined}ではないことに注意してください。それは、省略可能なパラメータが undefined でありうることが定義上明らかだからです。そのことを明示的に宣言しても不都合はありませんが、本来必要ないだけでなく、コードも読みにくくなってしまいます。

最後に、nullを許すことと省略可能であることは直交的な性質である点に注意してください。以下の4つの宣言は全て異なった意味を持っています:
/**
 * 4つの引数を取ります。そのうち2つはnullを許容し、2つは省略可能です。
 * @param {!Object} nonNull 必須(undefinedは不可)、nullは不可。
 * @param {Object} mayBeNull 必須(undefinedは不可)、nullでもよい。
 * @param {!Object=} opt_nonNull 省略可 (undefinedでもよい)、しかし値があるなら、
 *     それはnullであってはならない!
 * @param {Object=} opt_mayBeNull 省略可 (undefinedでもよい)、nullでもよい。
 */
function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) {
 // ...
};

型定義

時々、型の指定が複雑になってしまうことがあります。例えば、DOM要素のコンテンツを受け取る関数があるとしましょう:
/**
 * @param {string} tagName
 * @param {(string|Element|Text|Array.<Element>|Array.<Text>)} contents
 * @return {Element}
 */
goog.createElement = function(tagName, contents) {
  ...
};
@typedefタグを使うと、よく使われるデータ型の組み合わせを1つの型として定義することができます。例えばこうです:
/** @typedef {(string|Element|Text|Array.<Element>|Array.<Text>)} */
goog.ElementContent;

/**
 * @param {string} tagName
 * @param {goog.ElementContent} contents
 * @return {Element}
 */
goog.createElement = function(tagName, contents) {
  ...
};

テンプレート型

Compilerが行うテンプレート型のサポートは限定的です。それは関数リテラル内のthisの型を、thisを指定する引数の型と値の有無から推測するだけです。
/**
 * @param {function(this:T, ...)} fn
 * @param {T} thisObj
 * @param {...*} var_args
 * @template T
 */
goog.bind = function(fn, thisObj, var_args) {
  ...
};
// おそらくプロパティが存在しないという警告が出力されます。
goog.bind(function() { this.someProperty; }, new SomeClass());
// thisがundefinedであるという警告が出力されます。
goog.bind(function() { this.someProperty; });

列挙型

訳注:2.28版以降列挙型に関する以下の説明は削除されていますが、コーディングルールの理解には必要と考え記載します。
/**
 * 3つの状態を値にもつ列挙型。
 * @enum {number}
 */
project.TriState = {
  TRUE: 1,
  FALSE: -1,
  MAYBE: 0
};
列挙型は有効なデータ型の1つである点に注意して下さい。列挙型はパラメータの型指定などに使用できます。
/**
 * プロジェクトの状態を設定します。
 * @param {project.TriState} state 新しいプロジェクトの状態
 */
project.setState = function(state) {
 // ...
};



記事メニュー
目安箱バナー