最終更新日 2024-09-25

.NETのTypeScript型定義ファイルの生成

概要

hmV8用のマクロは、ECMAScript6で記述しても良いですが、
TypeScriptで記述する、という選択肢が最有力となります。

TypeScriptで記述することで、ECMAScript部分の型の間違いが事前に解消されるだけでなく、
hmV8が利用可能な「.NET Frameworkライブラリ」の入力補完も手堅い形で可能となります。

Visual StudioやVisual Studio Codeで TypeScriptを記述することで、hmV8用途の高度な補完環境を実現出来ます。

.NET Frameworkや、C#等で自作したdll用のTypeScript型定義ファイルの生成

入力補完上問題となりやすいのは、どちらかと言えばこちらです。

.NET Frameworkのメソッドやプロパティ名は、
Visual Studioの高度な入力補完が前提となっていることもあり、
大文字小文字が入り混じった長めのプロパティ・メソッド・型で構成される傾向が高く
入力補完に頼ることなく正確に入力していくのは、困難と言えます。

WinAssemblyToTypeScriptDeclare

そこで、.NET Frameworkのアセンブリや、自作のアセンブリを内部走査し、
自分で利用したい「.NETの指定のクラス」を、TypeScriptで入力補完が効くように
自動的にTypeScript型定義ファイルを生成するツールを作成しました。

ダウンロード

動作環境

使い方

以下はコンソール(cmd.exe)での例となっています。

コマンド概要
WinAssemblyToTypeScriptDeclare.exe [NameSpace] [Class] -deep:[0-2] -complex

となります。
探索対象は、「.NET 4系フォルダ」と「カレントフォルダ」の.dllとなります。
もしもC#等で自作した.dllを対象としたい場合、カレントフォルダにコピーすると良いでしょう。

具体例

「名前空間 System」の「Console」クラスをTypeScriptの宣言に
WinAssemblyToTypeScriptDeclare.exe System Console
上と同じだが、クラスや型の探索の深さが0層で済むようにする
WinAssemblyToTypeScriptDeclare.exe System Console -deep:0
名前空間に関わらず「Form」クラスをすべてTypeScritp風の型定義に
WinAssemblyToTypeScriptDeclare.exe any Form

PowerShellだと、「`1」といった文字列を引数として正しく扱えないため、
'List`1'や'Dictionary`2'といったように、シングルクォーテーションで引数を囲ってください。

1つのGenericパラメータがあるSystem.Collection.Generic のListクラスをTS型定義ファイルに
WinAssemblyToTypeScriptDeclare.exe System.Collections.Generic List`1
2つのGenericパラメータがあるSystem.Collection.Generic のDictionaryクラスをTS型定義ファイルに
WinAssemblyToTypeScriptDeclare.exe System.Collections.Generic Dictionary`2
宣言ファイルとしてはエラーが出る確率が高くなるが、複雑な型でも深度が許すなら極力anyにせず型情報に従う
WinAssemblyToTypeScriptDeclare.exe System Console -complex
Dictionaryに関する型を探索の深さが2層までTypeScritp風の型定義に
WinAssemblyToTypeScriptDeclare.exe System.Collections.Generic Dictionary`2 -deep:2
FormとButtonの2つのクラスをTypeScript風に
WinAssemblyToTypeScriptDeclare.exe System.Windows.Forms Form System.Windows.Forms Button

具体例を追ってみる

では、System.Windows.Forms FormとButtonを使う例を具体的に追ってみましょう。

System.Windows.Forms Form と System.Windows.Forms.Button クラスをTypeScritp風の型定義に
WinAssemblyToTypeScriptDeclare.exe  System.Windows.Forms Form  System.Windows.Forms Button > a.txt

として、まずは、FormのTypeScript型定義テキストを取得します。
これはコンソールの都合上、ShiftJISのファイルになってしまいますので、
エディタで開いて、全体をコピーし、ClrForms.d.tsなどといったファイル名にしてみましょう。

d.tsの中身のエラーを切る「-skipLibCheck」オプション

自動で生成したり、同じような型定義をreference pathすると、エラーが出ますので、
tasks.json(ご自分のTypeScriptの環境に合わせてください)で「-skipLibCheck」オプションを付けて、
TypeScript宣言ファイル(d.ts)についてはエラーが出ないようにしましょう。

ソースを実際に書いてみる。入力補完が効きまくる。

「b.js」といったファイルにしてみる
/// <reference path="hmv8.d.ts"/>
/// <reference path="ClrForms.d.ts"/>

let lib = host.lib("System.Windows.Forms");
let Forms: any = lib.System.Windows.Forms;
let Form: System.Windows.Forms.Form = Forms.Form;
let Button: System.Windows.Forms.Button = Forms.Button;

let f: System.Windows.Forms.Form = new Form();
let b: System.Windows.Forms.Button = new Button();
b.Text = "閉じる";

function b_Click(sender: any, e: any): void {
    f.Close();
}

b.Click.connect(b_Click)
f.Controls.Add(b);
f.ShowDialog();

入力補完が効くだけではなく、変数等をマウスで押し当てた時に、
それが一体何なのかが.NETに沿った情報が得られるのが良い。

トランスパイル

TypeScriptによってトランスパイルする(VSCodeの場合は、CTRL+SHIFT+B)

b.jsが出来上がります。

マクロファイルを用意

b.jsを読み込み実行するマクロファイルを用意しましょう。
「b.mac」
#JS = loaddll( hidemarudir + @"\hmV8.dll" );

#_ = dllfuncw(#JS, "DoFile", currentmacrodirectory + @"\b.js" );

freedll(#JS);

実行

ライセンス