あいつの日誌β

働きながら旅しています。

TypeScript と Node.js で hello, world をする http server を作る

Story: あらすじ

ひょんな事から TypeScript で Node.js のサーバーサイドエンジニアやる事になりました。

Enviroments: 環境

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.3
BuildVersion:   15D21

% node -v
v4.2.6

% npm -v
2.14.12

% tsc -v
message TS6029: Version 1.5.3

% dtsm -v
0.13.0

tsc と dtsm は以下のコマンドで入手しました。

% npm install -g tsc dtsm

Prepare: 準備

% mkdir practice-ts && cd $_ 
% npm init --yes

just do it: やってみる

create app.ts:

var http = require('http');

var server = http.createServer(function(req, res) {
  res.statusCode = 200;
  res.setHeader('Content-type', 'text/plain');
  res.write('Hello, TypeScript!');
  res.end();
});

server.listen(8080);
console.log('Server start.');

実は拡張子は .ts となっているのですが、このままだと普通の Node.js です。 なので node コマンドで実行できます。

% node app.ts
Server start.

ただしこのままでは tsc コマンドでコンパイルできません。

% tsc app.ts                                                                                                
app.ts(1,12): error TS2304: Cannot find name 'require'.

shell returned 2

declare type: 型を宣言するする

edit app.ts: 以下のように宣言を加えます。

+declare function require(x: string): any;
 var http = require('http');
 
 var server = http.createServer(function(req, res) {

コンパイルに成功しました。

% tsc app.ts && node app.js
Server start.

using packages: 用意された型を利用する

先ほどのやり方のように型の宣言を全部自分でやると大変です。 以下のようにすでにあるをインストールして利用します。

% dtsm init
% dtsm install node --save
node/node.d.ts #c29392

edit app.ts:

-declare function require(x: string): any;
+/// <reference path="./typings/bundle.d.ts" />
 var http = require('http');
 
 var server = http.createServer(function(req, res) {

./typings 以下で用意した declare を利用する事ができるようになりました。

import: 名前空間を利用する

TypeScript の型チェックを変数と引数に対して利用したいので以下のように修正したいと思います。

edit app.ts:

 /// <reference path="./typings/bundle.d.ts" />
 var http = require('http');
 
-var server = http.createServer(function(req, res) {
+var server: http.Server = http.createServer(function(req: http.ServerRequest, res: http.ServerResponse) {
   res.statusCode = 200;
   res.setHeader('Content-type', 'text/plain');
   res.write('Hello, TypeScript!');

ですがエラーが発生します。

% tsc app.ts
app.ts(4,13): error TS2503: Cannot find namespace 'http'.
app.ts(4,59): error TS2503: Cannot find namespace 'http'.
app.ts(4,84): error TS2503: Cannot find namespace 'http'.

import を使用します。

edit app.ts again:

 /// <reference path="./typings/bundle.d.ts" />
-var http = require('http');
+import http = require('http');
 
-var server = http.createServer(function(req, res) {
+var server: http.Server = http.createServer(function(req: http.ServerRequest, res: http.ServerResponse) {
   res.statusCode = 200;
   res.setHeader('Content-type', 'text/plain');
   res.write('Hello, TypeScript!');

今度は以下のように怒られます。

% tsc app.ts
app.ts(2,1): error TS1148: Cannot compile modules unless the '--module' flag is provided.

コマンドオプション --module commonjs を追加します。

% tsc app.ts --module commonjs && node app.js
Server start.

これで作業は終了です。お疲れ様でした。

まとめ

間違えてる場合はツッコミしてもらうとありがたいです。

  • node.js で TypeScript を書くときは imortrequire() を使い、 tsc コマンドのオプションに --module commonjs を指定する必要がある
  • DefinitelyTyped などの package 化された型を利用する方法はいくつかあるが dtsm コマンドから入っておけばたぶん大丈夫
  • typings/node/node.d.ts の冒頭に Node.js v4.x API と書いてあるので Node.js v5.X に対応しているかどうかよく分からない
  • 2016年2月2日現在、hatena に TypeScriptシンタックスハイライトは存在しない

参考URL

この記事は以下を参考に書きました。