I’ve been working on a new project over the last weeks that involves getting TypeScript and Electron working together. Unfortunately, the amount of information available on how to do this correctly is pathetically none existent.
That isn’t to say there aren’t sites that don’t try. But in the end, all they show you is how to write essentially the same JavaScript code you would have written using JavaScript with a little bit of type information thrown in. What I was looking for was something a little more object oriented. Let’s use ALL of TypeScript.
And then there is the whole setup of TypeScript in Node thing. This was mostly my not knowing my editor well. But while we are documenting how to get a TypeScript/Electron app setup, let’s cover that as well.
TypeScript and Electron Project Setup
I’m using Node 12 and VS Code as my editor (for the record). But most of what I am about to explain will work regardless of which editor you are using.
The first thing you want to do is to initialize your project using
Package.JSON
npm init
Just walk through the prompts and answer the questions. There isn’t much in the initialization process that will make any difference to what we are going to do, we need the resulting package.json file to store the package references we will install.
Next, install electron. You’ll want to do this globally and as part of your DEV environment.
npm install -g electron
And then use link to make it part of your local environment
npm link electron
and then install the types for electron
npm install --save-dev @types/electron
TypeScript
Next, you’ll need to setup TypeScript. For this, you’ll need a tsconfig.json file in your root. I’ll give you the file you’ll need here:
The thing that drove me crazy for several hours when I originally did this in WebStorm is that you also need to configure your editor to see this. VS Code seems to be able to locate the file without any trouble. I’ll leave that step for you because it will depend on which editor you are using.
The Electron Shell with TypeScript
Now comes the fun part. The normal code for creating the shell for an Electron application in JavaScript normally looks something like this:
The trick we want to perform is to create a TypeScript class that does essentially the same thing but using TypeScript syntax.
As you can see from the code above, there are a lot of variables that we are hanging on to. And since this is a desktop application, like most desktop applications, our entry class is going to need a static entry method. In fact, to work reliably, the whole class is going to need to be static.
Start by creating a Main class. Each of the event handlers will be a static function that is initialized when we call the main method. And to keep things clean we are going to inject the Electron stuff into the class via the main() method rather than having the class create those dependencies. This will make everything more testable.
The class we end up with looks like this:
To finish this up, we create an App.ts file that calls this class.
Compiling to JavaScript
You’ll need to compile the TypeScript into JavaScript so that Electron will be able to run your files. But before we do this, let’s install typescript locally so the version we use for this project only impacts this project.
npm install --save-dev typescript
Now, go into your package.json file and look for the scripts section and add a script called build that calls typescript:
"scripts": {
"build": "./node_modules/.bin/tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
And now you can build using
npm run build
And now we run using electron passing App.js as the file to run.
electron app.js
And, once you have your TypeScript code compiled down to JavaScript, all of the existing articles about how you would create a binary file for the various platforms apply. So I won’t bother to cover that here.
Production Ready
You’ll notice that compiling our TypeScript files by simply typing tsc
places all of the JS files in the same directory as our TS files. If we modify the tsconfig.json file to include
"outDir": "dist"
As part of the compilerOptions
block, all of our JS files will be placed in the dist
directory hanging off the root. This will keep your directory structure cleaner. Just remember that when you want to run the electron
command, you’ll need to run app.js
from the dist
directory
electron dist/app.js
Did I miss a step? Let me know in the comments below.