第9回 連想配列の取り扱い方TypeScriptで学ぶJavaScript入門(4/4 ページ)

» 2015年01月29日 15時13分 公開
[羽山博,]
前のページへ 1|2|3|4       

インデックスや要素のデータ型を指定するには

 ここまでサンプルプログラムをいくつか見てきたのだが、TypeScriptのプログラムとして、何か違和感を覚えることはなかっただろうか。TypeScriptではコンパイル時にデータ型をチェックして、不正な値が設定されることをあらかじめ防いでいるのに、プログラムをよく見てみると、連想配列ではどんなデータ型の値でも代入できてしまうことが分かる。

 TypeScriptではインデックスシグネチャと呼ばれる仕組みによって、インデックスや要素のデータ型を指定できるようになっている。最初に見たプログラムと同じ働きをする例で見てみよう。

var Player: { [index: string]: string; } = { Pitcher: "岩田", Catcher: "梅野" };
alert(Player["Pitcher"]);
window.close();


 インデックスシグネチャは全体を{}で囲み、[]の中にインデックスとそのデータ型を書き、その後に連想配列の要素のデータ型を書く。

図10 インデックスシグネチャを使って、連想配列のデータ型を指定する 図10 インデックスシグネチャを使って、連想配列のデータ型を指定する
「index」の部分は、別の名前でも構わない(例えば、keyなどと書いても構わない)。

 このようにして、連想配列のデータ型を指定しておけば、誤って名前の代わりに背番号を設定しようとして以下のような文を書いてしまった場合でもエラーになる。

Player["center"] = 0;  // エラーになる

string型が期待されている要素に数値型の値を代入しようとした(TypeScript)

 インデックスシグネチャを指定していない最初のプログラムでは、この文はエラーにならない。もちろん、文字列なら代入できるので、以下のように書くことはできる。

Player["center"] = "0"// エラーにならない

""で囲めば、数値ではなく文字列として扱われる(TypeScript)

 なお、インデックスシグネチャを追加すると、プログラムがやや読みづらくなるので、interfaceと呼ばれるキーワードを使って、インデックスシグネチャに名前を付けておくこともできる。

interface Dictionary {
  [index: string]: string;
}
var Player: Dictionary = { Pitcher: "岩田", Catcher: "梅野" };
alert(Player["Pitcher"]);
window.close();


 interfaceキーワードについてはまた回をあらためて詳しく説明するが、書き方としては、「interface」の後に、自分で型名を書き、その後にインデックスシグネチャの内容をそのまま書くだけである。そして、それまで、インデックスシグネチャを書いていた箇所に型名を書けばよい。

図11 interfaceキーワードを使って、インデックスシグネチャを見やすくする 図11 interfaceキーワードを使って、インデックスシグネチャを見やすくする
interfaceキーワードの後に指定した型名の後にインデックスシグネチャを書き、その型名を変数の宣言で使う。

 インデックスシグネチャを指定すると、配列の要素に不正なデータ型の値が代入されなくなる。しかしながら、インデックスに関しては、現時点ではデータ型がチェックされていないようである。

 例えば、以下のように書いても正しく動いてしまう。

// インデックスのデータ型を数値型としているが……
var Player: { [index: number]: string; } = { Pitcher: "岩田", Catcher: "梅野" };

// インデックスのデータ型を文字列型としているが……
var Player: { [index: string]: string; } = {};
Player[0] = "大和";

インデックスシグネチャを指定しても、インデックスにはどんなデータ型も使える(TypeScript)

 上の文では、インデックスに数値型を指定しているが、数値を使わなくてもエラーにならない。また、下の2行では、インデックスにも要素にも文字列型を指定しているが、インデックスに数値を指定してもエラーにならない。

 以下のコラムと併せて、データ型のチェックに関する落とし穴になる可能性があるので、注意してほしい。

[コラム]any型の値はnumber型の変数やstring型の変数に代入できる

 TypeScriptではデータ型のチェックがコンパイル時に行われるので、実行時に、期待したものと異なる型の値が代入されてしまうというエラーをあらかじめ取り除いておけます。しかし、any型に関してはちょっとした注意点があります。常識的に考えると「any型の変数にはどんなデータ型の値も代入できるが、特定のデータ型(例えばnumber型)の変数にany型の変数の値を代入するような文はエラーとなる」と思われます。しかし、実際にやってみると、any型の変数の値は他の型の変数に代入できます。

var a: number = 1;    // (1)
var b: any = "hoge"// (2)
a = b;  // (3)
alert(a);
window.close();


 (1)を見ると、変数aは数値型であることが分かります。(2)では変数bがany型になっています。(3)は、常識的に考えるとエラーになりそうですが、エラーにならずちゃんとコンパイルされます。変数aには"hoge"という文字列が代入されるので、このプログラムを実行するとアラートボックスに「hoge」と表示されます。any型の値に関しては、TypeScriptによる型チェックは最小限しか行われないので注意しましょう。


配列のインデックスに文字列を指定する方法

 では、最後に補足として、Array型を使った連想配列の作り方について見ておこう。普通は、オブジェクトのプロパティを使って連想配列を作るが、実は、Array型の配列を宣言し、インデックスに文字列を指定することによっても連想配列が作成できる。

var Player: string[] = new Array(9);  // (1)
Player["Pitcher"] = "岩田";
Player["Catcher"] = "梅野";
alert(Player["Pitcher"]);
window.close();


 実行結果は最初の例と同じものになる。これを見ると、宣言の方法は通常の配列と全く同じだということが分かる。また、インデックスの指定方法も、数値ではなく文字列を指定するだけなので、使い方もそう変わらない。もちろん、(1)の部分は以下のように書いてもよい。

var Player: Array<string> = new Array( 9 );

配列の宣言の別の書き方(TypeScript)

 種明かしをすると、ArrayオブジェクトはObjectオブジェクトを継承しているので、Objectオブジェクトの機能が使えるというわけだ。例えば、以下のようにプロパティとして取り扱うこともできる(ただし、TypeScriptではエラーになる)。

alert(Player.Pitcher);

ArrayオブジェクトはObjectオブジェクトを継承しているので、Objectオブジェクトのようにプロパティを使って連想配列の要素を取り出すこともできる(JavaScript)

 なお、「補足の蛇足」なのだが、少し前に触れたprototypeオブジェクトに関しても、継承をさかのぼって検索される。従って、以下のように書くと、ArrayオブジェクトからObjectオブジェクトへとさかのぼってプロパティが検索され、アラートボックスに「和田」と表示される。

var Player: string[] = new Array(9);
Player["Pitcher"] = "岩田";
Player["Catcher"] = "梅野";
Object.prototype["Manager"] = "和田";
alert(Player["Manager"]);
window.close();



 今回はTypeScriptの連想配列を取り上げた。連想配列はObjectオブジェクトのプロパティに他ならない。また、TypeScriptではインデックスシグネチャを使って連想配列の要素のデータ型が指定できる。それと関連して、いくつかの落とし穴があることも分かったと思う。

 次回は、関数を取り上げる。TypeScriptではアロー関数式(ラムダ式)やジェネリックといったJavaScriptにはない機能が利用できる。関数の基礎から始め、これらのTypeScriptの便利な機能についても詳しく解説する。

「TypeScriptで学ぶJavaScript入門」のインデックス

TypeScriptで学ぶJavaScript入門

前のページへ 1|2|3|4       

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。