Using TypeScript in a Phoenix Project

Using TypeScript in a Phoenix Project
For the last two years I have been working mostly with Typescript when developing for the front-end and it has fast become my preferred default. Unfortunately Typescript is not part of the default setup when starting a new project with the Elixir Phoenix Framework, so there are some steps I regularly have to go through to setup Typescript in a new Phoenix project.

mix phx.new my_app 
cd my_app/assets 
npm install npm install --save-dev typescript @babel/preset-typescript eslint eslint-config-prettier eslint-plugin-prettier prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin 
lang-bash

Once we have installed TypeScript and a few other necessities you will then need to add tsconfig.json and a tslint.json configuration files.
// my_app/assets/tsconfig.json 
{ 
  "compilerOptions": { 
    "target": "es5", 
    "module": "esnext", 
    // Search under node_modules for non-relative imports. 
    "moduleResolution": "node", 
    // Process & infer types from .js files. 
    "allowJs": true, 
    // Don't emit; allow Babel to transform files. 
    "noEmit": true, 
    // Enable strictest settings like strictNullChecks & noImplicitAny. 
    "strict": true, 
    // Disallow features that require cross-file information for emit. 
    "isolatedModules": false, 
    // Import non-ES modules as default imports. 
    "esModuleInterop": true 
  }, 
  "include": ["src"] 
}
lang-json

// my_app/assets/tslint.json 
{ 
  "rulesDirectory": ["tslint-plugin-prettier"], 
  "extends": ["tslint-config-prettier"], 
  "rules": { "prettier": true }
}
lang-json

Then we need to tell Babel to use the Typescript preset by adding @babel/preset-typescript to your .babelrc file. Then it should look like below:
// my_app/assets/.babelrc 
{ 
  "presets": ["@babel/preset-env", "@babel/preset-typescript"] 
}
lang-json

Typescript files use a .ts file extension, so we need to change the default Phoenix .js files over to use this extension. Also while making this change I rename the js directory to src.

You should then have a structure in your assets directory like below (some files omitted for brevity).
- css 
- node_modules 
- src 
- app.ts 
- socket.ts 
- static 
- vendor

Then lastly we need to make a few changes to the Webpack configuration so it is aware of the news files and structure. First we need to change the entrypoint to use our new src directory and app.ts file.
{  
  entry: {  
    './src/app.ts': ['./src/app.ts'].concat(glob.sync('./vendor/**/*.js')) 
  }, 
}
lang-typescript

Then we need to update the Babel loader to transpile files with a .ts extension.
{  
  test: /\.ts$/,  
  exclude: /node_modules/,  
  use: {  loader: 'babel-loader' } 
}
lang-json

Then you can fire up your Phoenix application with mix phx.server and you are ready to write your client side functionality in Typescript. You can check your up and running with a simple typed function like below, which Phoenix should then live-reload and display the prompt.
const say=(message: string) => alert(message); 

say("Hello world!");
lang-typescript

Written by Ben Barber

A software engineer and data-driven trader from Cambridge, UK. Currently working full-time on developing trading algorithms for the US equity and options markets.

Don't miss the next post!

Subscribe to get future posts via email

Add your email address below to get notified when I publish new posts.

No spam ever. Unsubscribe anytime.