TypeScript で jQuery のプラグインを書く

jQuery のプラグインを書くお作法みたいのがあって、だいたいどのプラグインも以下のように書かれている

(function($) {
  $.fn.myPlugin = function() {
      ...
  };
}) (jQuery);

これTypeScriptで書こうと思ったらこんな感じになった。

/// <reference path="path/to/jquery.d.ts" />

module jQuery {
  var $:JQueryStatic = <JQueryStatic>jQuery;

  $.fn.myPlugin = function() {
      ...
  };
}

jQuery モジュールを定義すると外側の即時関数は大体同じにコンパイルされる。
ただしこうすると jquery.d.ts の jQuery の定義を上書きしてしまうらしいので、$ に型アノテーション付きで jQuery を代入する。コンパイル結果は以下のようになって、だいたいお作法どおりになる。

var jQuery;
(function (jQuery) {
  var $ = jQuery;
  $.fn.myPlugin = function () {
    ...
  };
})(jQuery || (jQuery = {}));

モジュールとして宣言した jQuery をキャストするの気持ち悪くない?

気持ち悪いと思う。
だから最初外側の即時関数ぶぶんそのままでいいじゃんと思ったのだけれど、TypeScript では関数の内部にクラスを宣言できないっぽい。

(function($) {
  $.fn.myPlugin = function() {
      ...
  };
  ...
  class Hoge { // コンパイルエラー
    ...
  }
}) (jQuery);

自分のプラグインで使うクラスを定義したかったのでちょっと変なキャストするしかないのではないかと思った。なにか他にいい方法あったら誰か教えて下さい。

「自己紹介 あなたへ30の質問」に回答!

自己紹介 あなたへ30の質問

社会人力の高い新人との呼び声高い id:pokutuna から30もの質問をされたので答えます

01. みんなから何て呼ばれてる?

はっつ、はつしば

02. 自分の自慢できるところは?

シュウ酸カルシウム結晶の精錬

03. 自分の弱点は?

たまに腰に激痛が走る

04. 自分の口癖は?

うーん

05. 持ってるケータイの機種は?

iPhone 5

06. カラオケでよく歌う歌は?

音痴なんですよ・・・

07. 過去に似ていると言われたことのある芸能人は?

人形の久月のCMの人形に似てると言われたことがあります

08. 座右の銘は?

座右の銘
今度までに考えておきます

09. 将来の夢は?

みんなが幸せ

10. ブログをはじめたきっかけは?

ちょっと初対面の人には教えられないっすね

11. 好きなアニメは?

ガンダムUC

12. 好きなゲームは?

地球防衛軍。7月4日に4が出るので買いましょう!

地球防衛軍4 (初回購入特典 DLC搭乗兵器同梱)

地球防衛軍4 (初回購入特典 DLC搭乗兵器同梱)

13. 好きな食べ物は?

美味しそうな食べ物の画像を見るとその瞬間はそれが好きな食べ物になります

14. 好きな飲み物は?

美味しいビール

15. 好きな動物は?

動物あんまり得意じゃないけど子猫は卑怯だと思います

16. 好きな色は?

青色方面

17. 好きな芸能人は?

三人そろって Perfume です!

18. 好きなファッションブランドは?

この夏のマストアイテムははてなTシャツじゃないっすかね

19. 好きな雑誌は?

あんまり読まない

20. 好きなスポーツは?

昔バドミントンやってましたけどもう無理なのでたまに山に登ったりしてます

21. 昨日晩ご飯に何を食べた?

餃子

22. 最近見た夢を教えて!

コードレビューでことごとくダメ出しされて、「つらいっ」って言って起きる夢を今朝見ました

23. 最近読んでおもしろかった本を教えて!

なんだろ

24. 最近見ておもしろかったテレビ番組を教えて!

雲の階段っていうドラマを毎週見てました。あんまり視聴率よくなかったみたいですけど緊迫感があっていつも見入ってました。

25. マイブームを教えて!

登山

26. 旅行するとしたらどこに行きたい?

ウユニ塩湖にどうにか行きたい

27. 明日地球が滅びるとしたら何がしたい?

いんたーねっと

28. 自分を一言で表すと?

表して下さい

29. 自分の秘密を1つ教えて!

君たちを巻き込むわけにはいかない

30. 次に答えてほしい人をidコールしよう!

id:nobuoka さんオナシャス

grunt-typescript で型チェックエラーを無視する

バッドな感じのタイトルだけど、開発中にとりえあず型エラーが出ていてもとりえあずjsファイルを吐いてほしいときはある。

実際 tsc コマンドを打つと、syntax error のときは js を吐かないけど、型エラーのときは js を吐いている。(それが好ましいのかどうかはしらないけど。)

  • hoge.ts
class Hoge {}
var h = new Hoge();
h.hoge();

Hogeクラスにhogeメソッドなんてないので型エラーがでるけど、jsファイルはできてる。

$ tsc hoge.ts
hoge.ts(3,2): The property 'hoge' does not exist on value of type 'Hoge'
$ ls
hoge.js hoge.ts
  • hoge.js
var Hoge = (function () {
    function Hoge() { }
    return Hoge;
})();
var h = new Hoge();
h.hoge();

grunt-typescript では型エラーが出るともう js 吐かない。ちょっと動作確認だけしたいみたいなときにもちゃんと型の整合性を取る必要があるので、"型付けを後回し"にすることができない(すべきじゃないとか言われそう)


ので grunt-typescript にオプションを足してみる

diff --git a/tasks/typescript.js b/tasks/typescript.js
@@ -306,7 +306,7 @@ module.exports = function (grunt) {
             }
         });
         compiler.typeCheck();
-        if(compiler.errorReporter.hasErrors){
+        if(compiler.errorReporter.hasErrors && !options.ignoreTypeCheck){
             return false;
         }
         compiler.emit(io);

Gruntfile の typescript のオプションに ignoreTypeCheck: true を足したら型エラーが出ても js ファイル吐き出してくれた。
タスク自体は失敗になるので注意。

Backbone.jsガイドブック

Backbone.jsガイドブック

dart で mysql にアクセスする

dart で mysql を扱うときのメモ。
dart の mysql ドライバーには sqljocky というのがあるようなので使ってみる。
dartEditor っていう Eclipse の亜種みたいのがあるのでそれ使ってもいいかもだけどとりえあず今回はなしで。

インストール

OSX で作業してるので dart のインストールは homebrew でささっと。

brew install dart

dart には pub というパッケージマネージャがあるのでこれを使ってインストールする。
まずアプリケーションのホームディレクトリに pubspec.yaml というファイルを作成し、以下のように記述する

name: appname
dependencies:
  sqljocky: any

dependencies 以下に依存モジュールを記述していく。any はバージョンの指定で、any だとたぶん最新版がインストールされる。バージョンを指定したい場合には

dependencies:
  sqljocky: 0.5.1

のように記述する。pubspec.yaml の準備が完了したら pub コマンドを実行する

pub install

pub に付いて詳しくは Getting Started | Pub Package Manager を参照した。

mysql にアクセス

まずはインストールした sqljocky モジュールを import する。

import 'package:sqljocky/sqljocky.dart';

昔 #import だった気がするけど変わったのかな。結構前から変わってるのかも。

実際に mysql にアクセスするコードは以下の感じ。

void main () {
  var pool = new ConnectionPool(
    host: 'localhost',
    user: 'user',
    password: 'pass',
    db: 'test',
    max: 1
  );

  pool.query('select * from user').then((result) {
    result.stream.listen((row) {
      print(row[0]);
    }, onDone: () {
      pool.close();
    });
  });
}

node書いてる人とかだとコード見ればだいたい何やってるかわかりそう。
dart でもIOはだいたいノンブロッキングになっていることが多いようで、query メソッドの返り値はDBから取得したレコードとかじゃなく、Future 型のオブジェクト。

この Future オブジェクトというのは jQuery の Deferred.promise オブジェクトとだいたいおんなじものだと思ってよさそう。dart:async モジュールにリファレンスがある

Future<T> abstract class / dart:async Library / Dart API Reference

ちゃんと見てないけど、then に渡すコールバックに渡されてくる result オブジェクトをまた listen すると、一行取得するごとにその下のコールバックが呼ばれる。DBのレコードをModelオブジェクトにマッピングするのはここでやれば良さそう。
全部読み終わると onDone に渡したコールバックが呼ばれる、って言う感じ。

then の呼び出しはまた新しい Future オブジェクトを返すので、select した結果をもとにどうこうしたい場合には、thenをつなげるとよい

pool.query(...).then((...) {
  ...
}).then((...) {
  ...
})

といった感じになる。非同期処理で同期的な処理を書くのがどうしても冗長だし直感的じゃないコードになるのだけど何かいい方法/書き方ないのだろうか。。

What is Dart?

What is Dart?