TypeScript でコードを書くとコンパイル時に問題を報告してくれてうれしいんですが、既存の JavaScript と組み合わせるときに型の定義を手動で書く必要があってつらみがあります。そこんところを自動でやってくれる dtsmake というツールがあったので使ってみます。

インストール

npm でインストールできます。

$ npm install -g dtsmake

js から d.ts を作る

適当な JavaScript を用意してみます。

// a.js

var a = {};

a.add = function(a, b) { return a + b; };

これの型定義を dtsmake コマンドで生成します。

$ dtsmake -s a.js

これで a.d.tsa.js のとなりに作られます。それが以下です。

// Type definitions for a.js
// Project: [LIBRARY_URL_HERE] 
// Definitions by: [YOUR_NAME_HERE] <[YOUR_URL_HERE]> 
// Definitions: https://github.com/borisyankov/DefinitelyTyped

/**
 * a.js
 */
declare namespace a{

    /**
     * 
     * @param a 
     * @param b 
     */
    function add(a : any, b : any): void;
}

a というオブジェクトがあって add というメソッドがあることがわかります。

使うがわのコードをヒントとして与える

さっきの例だと a.add というメソッドがあることは理解してくれましたが、型が (a: any, b: any) => void 型になってしまいました。実際に引数にどういう値が入るのかを、実際のコードをヒントとして与えることができます。

// b.js

a.add(1, 2);

a.add12 を引数として渡しました。これをヒントとして与えるには -x オプションを使います。

$ dtsm -s a.js -x b.js

これを実行すると a.add の型が詳細になります。

function add(a : number, b : number): number;

これで a.add が数値を受け取って数値を返すメソッドだという型定義ファイルが生成できました。

npm モジュール

上の例だとグローバルに a というオブジェクトを作っていました。ブラウザだとこんな感じだと思いますが、 Node だと CommonJS で書くと思います。それを変換するにはいくつかオプションを指定します。

$ dtsmake -s a.js -x b.js -e -M a -n a

-eexports 方式であることを指定します。 -M a は npm でのモジュール名が "a" であることを指定します。 declare module "a" というコードが生成されます。 -n a はネームスペースが a であることを示します。指定しないとちゃんとしたコードを出してくれませんでした。

生成されたコードが以下です。

// Type definitions for a
// Project: [LIBRARY_URL_HERE] 
// Definitions by: [YOUR_NAME_HERE] <[YOUR_URL_HERE]> 
// Definitions: https://github.com/borisyankov/DefinitelyTyped

/**
 * 
 */
declare namespace a{

    /**
     * 
     * @param a 
     * @param b 
     * @return  
     */
    function add(a : number, b : number): number;
}

declare module 'a' {

    export = a;    //legacy ts module export
}

declare module "a" の型定義があることがわかります。

まとめ

dtsmake で JavaScript から TypeScript の型定義ファイルを生成してみました。型が不完全だったりオプションをいろいろ指定する必要なんかもありますが、うまく使えば作業を簡単にできそうです。最初にたたき台を生成するだけの使い方もできそうです。