Electron を TypeScript で書く
Electronを動かしてHello world!表示するまで(macOS) で試作したElectronアプリを、JavaScript から TypeScript へ書き換えてみました。
JSからTSへ移行する流れ
- Electronアプリで作成したjsとhtmlファイルをsrcへ移動
- jsファイルは拡張子をtsへ変更(内容も適宜変更)
- tsconfig.jsonを用意する
- package.jsonを修正する
sh
$ tree -I node_modules
.
├── default.txt
├── dist
│ ├── index.html
│ ├── main.js
│ └── preload.js
├── package-lock.json
├── package.json
├── src
│ ├── index.html
│ ├── main.ts
│ └── preload.ts
└── tsconfig.json
JSからTSへ移行する手順
それでは既存のElectronプロジェクトをTypeScriptに移行していきます。
TypeScriptのインストール
プロジェクトディレクトリで以下のコマンドを実行して、TypeScriptをインストールします。
sh
npm install --save-dev typescript
tsconfig.jsonの作成
プロジェクトのルートディレクトリにtsconfig.jsonファイルを作成し、以下の内容を追加します。
json
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"resolveJsonModule": true,
"noImplicitAny": true,
"moduleResolution": "node",
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
プロジェクト構造の変更
JavaScriptファイルをTypeScriptファイルにリネームします。例えば、main.jsをmain.tsに変更します。src ディレクトリも作成し、そこへソースコードを移動させておきます。
ビルドスクリプトの設定
package.jsonにビルドとコピーのスクリプトを追加します。ここではcopyfilesパッケージを使用して、HTMLファイルをコピーします。
sh
npm install --save-dev copyfiles
次に、package.jsonのスクリプトセクションを以下のように更新します。
json
"scripts": {
"build": "tsc && npm run copy-html",
"copy-html": "copyfiles -u 1 src/*.html dist",
"start": "npm run build && electron ./dist/main.js"
},
必要な型定義パッケージのインストール
Electronの型定義パッケージをインストールします。
sh
npm install --save-dev @types/node @types/electron
ソースコードの修正
TypeScriptの型定義に従って、ソースコードを修正します。例えば、requireを使用している部分をimportに置き換えるなど。
ts
// src/main.ts
import {app, BrowserWindow, ipcMain, dialog} from 'electron';
import fs from 'fs';
import path from 'path';
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
}
});
win.loadFile('index.html');
win.webContents.openDevTools();
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
ipcMain.on('save-file', async (event: { reply: (arg0: string, arg1: string) => void; }, data: any) => {
const result = await dialog.showSaveDialog({
title: 'Save File',
defaultPath: path.join(__dirname, 'default.txt'),
buttonLabel: 'Save',
filters: [
{ name: 'Text Files', extensions: ['txt'] },
{ name: 'All Files', extensions: ['*'] }
]
});
if (!result.canceled) {
fs.writeFile(result.filePath.toString(), data, (err: any) => {
if (err) {
console.error('File Save Error:', err);
event.reply('save-file-response', 'error');
} else {
console.log('File Saved Successfully');
event.reply('save-file-response', 'success');
}
});
} else {
event.reply('save-file-response', 'canceled');
}
});
また、型指定ができるようになるので、WebStormなどのIDEの機能を使って内容を適宜修正します。
ts
// src/preload.ts
import {contextBridge, ipcRenderer} from 'electron';
contextBridge.exposeInMainWorld('electron', {
saveFile: (content: any) => ipcRenderer.send('save-file', content),
onSaveFileResponse: (callback: (event: Electron.IpcRendererEvent, ...args: any[]) => void) => ipcRenderer.on('save-file-response', callback),
});
プロジェクトのビルドと実行
以下のコマンドでプロジェクトをビルドし、Electronアプリを実行します。
sh
npm run start
これで、既存のElectronプロジェクトをTypeScriptに移行する基本的な手順は完了です。