TypeScriptの練習をかねて,OpenLayersを使っているJavaScriptをTypeScriptにしてみる実験です.※最新版のTypeScript定義は,GitHub でメンテしています.
TypeScriptについての説明は省略します.TypeScriptのセットアップ(Windows XP)は,以下の手順で行いました.
(1) node.jsをインストールする
http://nodejs.org/
node-v0.10.12-x86.msi をダウンロードして実行
(2) コマンドプロンプトから
npm install -g typescript
を実行する
ソース
以下のhtmlとtsファイルを準備します.普通にOpenLayersを使って地図を表示して,
マーカーを
LonLat(135.220825,34.796897)
の位置(神戸電鉄 有馬口駅)に表示するスクリプトです.
test.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js" charset="UTF-8"></script>
<script type="text/javascript" src="test.js" charset="UTF-8"></script>
</head>
<body onload="init()">
<div id="map" style="width:400px;height:400px;"></div>
</body>
</html>
次のファイルは拡張子がtsですが,見ての通り実体はJavaScriptです.先頭にreference pathが付いているという違いだけです.
test.ts
/// <reference path="openlayers.d.ts" />
var
proj900913 = new
OpenLayers.Projection("EPSG:900913"
);
var
proj4326 = new
OpenLayers.Projection("EPSG:4326"
);
var
msize = new
OpenLayers.Size(25, 35);
var
moffset = new
OpenLayers.Pixel(-(msize.w/2), -msize.h);
var
icon = new
OpenLayers.Icon('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=S|B0B0FF|000000'
,
msize, moffset);
function
init() {
var
applyZoomLv = 15;
var
maxExtent = new
OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508);
var
restrictedExtent = maxExtent.clone();
var
maxResolution = 156543.0339;
var
mapOptions = {
controls: [
new
OpenLayers.Control.Navigation({mouseWheelOptions: {interval: 100}}),
new
OpenLayers.Control.PanZoomBar(),
new
OpenLayers.Control.KeyboardDefaults(),
new
OpenLayers.Control.Attribution()
],
projection: proj900913,
displayProjection: proj4326,
units: "m"
,
maxResolution: maxResolution,
maxExtent: maxExtent,
restrictedExtent: restrictedExtent
};
var
map = new
OpenLayers.Map('map'
, mapOptions);
map.addControl(new
OpenLayers.Control.ScaleLine(
{maxWidth:150, bottomOutUnits: ""
, bottomInUnits: ""
, geodesic:true
}));
var
osmMap = new
OpenLayers.Layer.OSM();
map.addLayer(osmMap);
// marker setting
var
markerPos = new
OpenLayers.LonLat(135.220825,34.796897)
.transform(proj4326, proj900913);
var
markers = new
OpenLayers.Layer.Markers("Markers"
);
markers.addMarker(new
OpenLayers.Marker(markerPos, icon));
map.addLayer(markers);
map.setCenter(markerPos, applyZoomLv);
}
次は,先ほどのreference pathで参照していた,OpenLayersのTypeScript定義ファイルです.
OpenLayersのAPIドキュメント
を見ながら,今回使っている必要最小限だけ定義しました.
(本当はもっといい書き方があるかも知れません)
openlayers.d.ts 〜今回の必要最小限のみ
declare
module
OpenLayers {
class
Bounds {
constructor
(left: number
, bottom: number
, right: number
, top: number
);
clone(): Bounds;
}
class
Control {
}
module
Control {
class
Navigation extends
Control {
constructor
(options: any
);
}
class
PanZoomBar extends
Control {
}
class
KeyboardDefaults extends
Control {
}
class
Attribution extends
Control {
}
class
ScaleLine extends
Control {
constructor
(options: any
);
}
}
class
Icon {
constructor
(url: string
, size: Size, offset: Pixel);
}
class
Layer {
addMarker(marker: Marker): void
;
removeMarker(marker: Marker): void
;
}
module
Layer {
class
Markers extends
Layer {
constructor
(name: string
);
}
class
OSM extends
Layer {
}
}
class
LonLat {
constructor
(lon: number
, lat: number
);
transform(source: Projection, dest: Projection): LonLat;
}
class
Map {
constructor
(div: string
, options: _MapOptions);
addControl(controls: Control, px?: Pixel): void
;
addLayer(layer
: Layer): void
;
setCenter(lonlat: LonLat, level?: number
);
}
interface
_MapOptions {
controls: Control[];
projection: Projection;
displayProjection: Projection;
units: string
;
maxResolution: number
;
maxExtent: Bounds;
restrictedExtent: Bounds;
}
class
Marker {
constructor
(lonlat: LonLat, icon: Icon);
icon: Icon;
}
class
Pixel {
constructor
(x: number
, y: number
);
}
class
Projection {
constructor
(projCode: string
);
}
class
Size {
constructor
(width: number
, height: number
);
w: number
;
h: number
;
}
}
この3ファイルが揃ったら,コマンドプロンプトからtscでコンパイルしてみます.
C:\work\TypeScript>tsc test.ts
すると,test.js が出力されますので,ブラウザでtest.htmlを開くとそのjsを読み込んで地図が出ます.
TypeScriptを使う利点
これだけ見ると,こんなことをして一体何が嬉しいのか?となるかも知れません.
利点としては,ブラウザで実行しなくてもコンパイル時にエラーチェックができるということだと思います.
例えば,test.tsでnew OpenLayers.Map()に渡しているmapOptionsを,
ではなく
に間違えたとします.
すると,コンパイルで以下のようにエラーになります.
C:\work\TypeScript>tsc test.ts
C:/work/TypeScript/test.ts(30,27): error TS2082: Supplied parameters do not match any signature of call target:
Type '{ controls: OpenLayers.Control.Attribution[]; projection: OpenLayers.Projection; displayProjection:
OpenLayers.Projection; unit: string; maxResolution: number; maxExtent: OpenLayers.Bounds; restrictedExtent:
OpenLayers.Bounds; }' is missing property 'units' from type 'OpenLayers._MapOptions'.
C:/work/TypeScript/test.ts(30,27): error TS2085: Could not select overload for 'new' expression.
ブラウザで実行する前に,このように打ち間違いを排除できるのは,私は嬉しいですね (´∀`)
...後で気がつきましたが,これはあまり良くない例です.
unitsは別に必須ではないので,他の用途も想定すると,openlayers.d.ts の記述は
interface _MapOptions {
・・・
units?: string;
・・・
}
という省略可能の定義になると思います.
しかしそうすると,unitsの記述間違いのチェックはできなくなります.
jQueryのTypeScript定義でも,似たような問題というか限界があるようです.
参考