Visual Studio Codeを使ってJavaScriptだけ書くつもりだったのですが、TypeScriptの型情報があればIntelliSenseも便利に使えるということで、npmで使おうとしたモジュールに.d.ts
ファイルを用意してみることにしました。ただ、正しく動作させる方法がわからず、見様見真似で動くものにした、という感じです。
使ってみたnpmモジュール
また例によってパズルソルバーを作っていたのですが、その過程で「タテヨコにつながったマスの範囲」を調べる必要が出てきました。どこかに適当なライブラリはないかと探してみると、n-dimensional-flood-fillというのが見つかりました。
これは、require
すると、1つの関数が現れます。そして、そこにオプションを指定すると、返り値としてつながったものの座標の配列が来る、という流れになっています。
型宣言を作ってみる
まずは、引数と返り値の型宣言をしてみましたが、こちらはすんなり書けました。
interface NDimensionalFloodFillOptions<T>{
/**
* function getting a value from specified position.
*/
getter: (...position: number[]) => T;
/**
* initial position for flooding
*/
seed: number[];
/**
* a callback called when one cell is flooded. (optional)
*/
onFlood?: (...position: number[]) => any;
/**
* a callback called when one cell is marked as boundary. (optional)
*/
onBoundary?: (...position: number[]) => any;
/**
* a callcack deciding whether two cells are equal.
* default: comparison by ===
*/
equals?: (arg1: T, arg2: T) => boolean;
/** true if floodable to diagonal cells. (default: false) */
diagonals?: boolean;
}
なお、getter
で取ってくるものと、equals
で比較評価するものは同じ型のはずなので、<T>
でジェネリクスとしています。また、on***
の返り値は特に使わないので、チェック不要ということでany
としています。
interface NDimensionalFloodFillResult{
flooded: number[][];
boundaries: number[][];
}
「n
次元」という処理内容の都合上、一部の配列の要素数は同じと決まってくるのですが、それをTypeScript上で表現する方法は見つかりませんでした。
エクスポートするものの宣言…どうする?
そして、本題の関数について宣言してみるとこんな感じになります。
declare function floodFill<T>(options: NDimensionalFloodFillOptions<T>) : NDimensionalFloodFillResult;
ところが、これをモジュールでエクスポートしようとするとさあ大変でした。コンパイルが通らないとか、モジュールから直接関数にならずに、.floodFill
として置かれてしまうなど、なかなかうまく行きませんでした。結局、関数である$
をエクスポートしているjQueryの定義ファイルを参考に、関数でなくインターフェースとして用意してみることにしました。
interface NDimensionalFloodFillFunction{
<T>(options: NDimensionalFloodFillOptions<T>) : NDimensionalFloodFillResult;
}
declare var floodFill: NDimensionalFloodFillFunction;
declare module "n-dimensional-flood-fill"{
export = floodFill;
}
とすることで、とりあえずVisual Studio Codeでは使えるようになりました。ただ、この宣言だとグローバルにfloodFill
がいるということになってしまって、その不都合は残ったままとなっています。