[入門] node.js 6.11 (Electron 1.8) + Typescript 2.4 (2017年9月時点最新の方法)

どんどんバージョンが新しくなるので、検索で出てきた情報が使えなかったりと、結構ハマりました。とりあえず2017年9月時点で成功したやり方をまとめておきます。
* typings、DT使用しません。
* electron-prebuilt使用しません。
(TypeScript2ではtypingsとか不要って言ってるのに使ってるexample多すぎ！electron-prebuiltも！)
(ただし、この記事も怪しいので注意。こうして中途半端な日本語情報が増えていくのです。 **公式サイトのDocumentを確認するのが結局は一番早くて確実です。**)

この記事のゴール
![2017-09-03 22.11.18.jpg](https://qiita-image-store.s3.amazonaws.com/0/77793/7c1da1f9-8550-c8e6-3376-310a97c99664.jpeg)

# 環境

Visual Studio 2017

Visual Studio Installer にてnode.jsとTypeScriptを入れておく。

```
$ node -v
v6.11.2
$ npm -v
3.10.10
$ tsc -v
Version 2.4.1
```

TypeScriptは最新は2.5.xが出ているが、とりあえず2.4を使う。2.2だとビルドが通らなかった。

環境変数`Path`も念のため、`C:\Program Files (x86)\Microsoft SDKs\TypeScript\2.4` に通しておいた。


# 手順

node.js (TypeScript) で新規作成して、初期のapp.ts等を全て削除する。

npmで必要なライブラリをinstallしていく。

```
$ npm install electron --save
$ npm install jquery@3.2.1 --save
$ npm install @types/jquery@3.2.1 --save
```

electron公式のやり方（どこで見たか忘れた）に則って、`main` と `remote`というフォルダをプロジェクト直下に作成します。mainはサーバー側、remoteはクライアント側となります。

main/main.tsを作成して、以下をコピペ。公式サイトの記述をなるべくTypeScript的に直してみました。anyばっかりなのでかなり中途半端ですが。

```ts:main/main.ts
/// <reference types="electron" />

// import electron
var electron = require('electron');
var app: Electron.App = electron.app;
var ipcMain: Electron.IpcMain = electron.ipcMain;

// import standard library
var url = require('url');
var http = require('http');
var fs = require('fs');
var path = require('path');

let mainWindow: Electron.BrowserWindow;

function createWindow() {
    mainWindow = new electron.BrowserWindow({ width: 1200, height: 600 });
    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, '../remote/index.html'),
        protocol: 'file:',
        slashes: true
    }));

    // if you want use dev tools.
    mainWindow.webContents.openDevTools();

    mainWindow.on('closed', () => {
        mainWindow = null;
    });
}

app.on('ready', createWindow);
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

app.on('activate', () => {
    if (mainWindow === null) {
        createWindow();
    }
});
```

remoteの方にクライアント側を記述します。今後絶対使うと思ったのでjQueryの準備だけしておきました。

```html:remote/index.html
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script>
        window.jQuery = window.$ = require('../node_modules/jquery/dist/jquery.min.js');
    </script>
    <script src="./js/index.js"></script>
</head>
<body>
    <span id="dummy">test</span>
</body>
</html>
```

※ ここでjQueryの読み込みをrequireを使っているのも最新のやり方ではないはずですが、試行錯誤してこれしか上手くいかなかった。もっと根本の仕組みを理解していないと辛い。

jsフォルダにindex.tsを記述します。こんな感じでクライアント側の記述をしていくよ、という準備。クリックイベントを適当に貼ってみました。

```ts:remote/js/index.ts
/// <reference types="jquery" />

$(function () {
    $('#dummy').click(function() {
        alert('Hello World!');
    });
});
```

F5キーで実行した結果。

![2017-09-03 23.05.54.jpg](https://qiita-image-store.s3.amazonaws.com/0/77793/9c733779-1968-3ab0-b2ea-5f002bf23b84.jpeg)

試しに、clickイベントをclickeとしてみると、ビルドエラーとなります。TypeScriptの型チェックのおかげです。
```
エラー TS2551: Build:プロパティ 'clicke' は型 'JQuery<HTMLElement>' に存在していません。候補: 'click'。
```

実行は出来るようになりましたが、ブレークポイントが貼れない…。これは後日調査します。



## ポイント
* electron-prebuilt を使えといろんなサイトで言われていますが、electronで良い。electronだと最新が1.8.0(2017/8/31更新)ですが、electron-prebuiltだと1.4.13 (2016/12/20更新)が最新となっていて、現状ではelectronに統一されているようです。
* electronの型情報もそのままモジュールに入っている。
* jQueryは型情報を別で入れる必要がありましたが、jQueryは本体と@typesでバージョンを合わせる必要がありました。
* 当初、TypeScript2.2でビルドした際、@types/jqueryのindex.d.tsでビルドエラーになりました。 大量の `エラー TS2314: Build:ジェネリック型 'JQueryStatic<TElement, HTMLElement>' には 2 個の型引数が必要です。` TypeScript 2.4だと問題なくビルドできました。(後から気づきましたが、index.d.tsのコメントにTypeScript 2.3の記述がありますね。2.3以降なら問題ないようです。)
* typings等の型情報はTypeScript2 以降で`@types`を使用したやり方に代わりました。jQueryはそれに則ってます。
* ` /// <reference path="../../node_modules/electron/index.d.ts" />` ではなく `/// <reference types="electron" />` というシンプルな書き方が推奨されているようですが、どこを参照しているのかが明示的でなくなってしまいました。

## 参考
https://www.npmjs.com/package/electron
> You can currently use either name, but **electron is recommended, as the electron-prebuilt name is deprecated**, and will only be published until the end of 2016.

https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html
https://www.typescriptlang.org/docs/handbook/declaration-files/library-structures.html#consuming-dependencies
> Don’t use `/// <reference path="..." />` in your declaration files.
> Do use `/// <reference types="..." />` instead.