Add TypeScript support to Ruby on Rails - A quick and hacky example

Published: by Creative Commons Licence

As I'm currently learning TypeScript, I wondered if I could apply it to my little Ruby on Rails project Strafforts (A Visualizer for Strava Estimated Best Efforts and Races), so that I could use this real world project to help me learning TypeScript quickly.

Even though there is a gem called typescript-rails which is a Rails asset pipeline wrapper for the TypeScript, I have decided to create my own quick and hacky way of introducing TypeScipt to my Ruby on Rails project, mostly due to the following reasons:

  • The purpose is to learn TypeScript with all its setup process, so why not start from scratch by myself as I'm not trying to create a nice and complete solution for everyone.
  • typescript-rails project hasn't been updated for almost a year. Is it well maintained and fully compatible with the latest Rails 5.1.x?
  • Rails 5.1.x supports Yarn now. Why not try the traditional Node.js way instead of the Rails way?

Therefore I have added TypeScript support to my Ruby on Rails project in a quick and hacky way.

Install Yarn

Yarn is a JavaScript package manager, a quick, secure and reliable npm alternative. which is officially supported by Rails from version 5.1.

To install Yarn, please follow the official installation guide here. For macOS users, simply use homebrew brew install yarn.

Install TypeScript through Yarn

Initialize

For projects with Rails 5.1 or above, package.json should have been created automatically when app was created. Otherwise for older versions of Rails, use yarn init to create a package.json first.

Add TypeScipt package

Use the following command to add TypeScript package to the project.

yarn add typescript

It will create node_modules folder under project root and a yarn.lock file containing information about the package versions. If installation is successful, TypeScript binary should be accessible in node_modules/.bin/tsc.

Add to assets paths

For users with Rails 5.1 or above, this step should have been done automatically. But for users with older Rails versions, node_modules folder needs to be added to Rails assets paths manually.

To do so, add the following line to config/initializers/assets.rb:

Rails.application.config.assets.paths << Rails.root.join('node_modules')

Update .gitignore

For users with Rails 5.0 or under, once node_modules folder is created, remember to add it together with Yarn's error log file to .gitignore, so that they will not be commited to the repository.

/node_modules
/yarn-error.log

Write TypeScript

Now write some TypeScript to replace the existing CoffeeScript or plain JavaScript. For example, create a TypeScript file welcome.ts under app/assets/javascripts.

class HelloWorld {

    private name: string;

    constructor(name: string) {
        this.name = name;
    }

    print() {
        alert(`Hello World, ${this.name}!`);
    }
}

new HelloWorld('John Doe').print();

Add tsconfig.json

Typically, to guide TypeScript compiler on how to generate JavaScript files, add a TypeScript configuration file called tsconfig.json to the project.

The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. It specifies the root files and the compiler options required to compile the project.

Here for example, create a tsconfig.json file with some common options, and tell compiler to convert welcome.ts to generated/welcome.js, where everything in generated folder can be added to .gitignore.

{
  "compilerOptions": {
      "outFile": "app/assets/javascripts/generated/welcome.js",
      "noImplicitAny": true,
      "noEmitOnError": true,
      "sourceMap": true,
      "target": "es5"
  },
  "files": [
      "app/assets/javascripts/welcome.ts"
  ]
}

Add Rake build task

Finally create a new Rake task to compile to TypeScript files to JavaScript. Note that this new task can be added to Rails' rake assets:precompile task, so that every time rake assets:precompile is executed, assets:tsc will be run first.

namespace :assets do
  desc 'Compile TypeScript Files'
  task :tsc do
    system('node_modules/.bin/tsc')
  end
end

Rake::Task['assets:precompile'].enhance ['assets:tsc']

For example, add a assets.rake file to lib/tasks folder with the content above, then call the following command to compile TypeScript.

rake assets:tsc

Demos

A simple demo for this tutorial is hosted on GitHub.

The more complicated example that was actually applied to Strafforts can also be viewed on GitHub, which contains separate tsconfig.json files for compiling different pages/projects.