Why you should use TypeScript on the backend too

TypeScript first appeared in 2012 and the main goal was to help developers work on large scale applications, giving them tools to refactor, find references and more.

Very large JavaScript code bases tend to become read-only
— Anders Hejlsberg (//build/ 2016)

Today, as of the writing of this post, TypeScript is the 12th most popular language according to PYPL (PopularitY of Programming Language)¹.

All JavaScript is TypeScript

If you have been working with JavaScript and/or Node.js you have already being working with TypeScript in a way, because all JavaScript is TypeScript.

image from basarat’s Gitbook

TypeScript allows you to use all JavaScript features that are not yet supported by “JavaScript today”. When you transpile (“compile”) it converts your code to JavaScript that can run on the targeted ECMAScript version.

This is different from CoffeeScript, dart and other tools, as Scott Hanselman wrote in his blog:

People have compared TypeScript to Dart. That’s comparing apples to carburetors
 — Scott Hanselman

TypeScript uses the same syntax as JavaScript and it avoids changing your code whenever possible. It might change your code if you do something not supported by the target ECMAScript version, like using async/await targeting es5, in which case it would be equivalent to running Babeljs. Oh, and with TypeScript you won’t even need Babeljs anymore.

To use TypeScript and get all of its benefits on Nodejs all you need to do is install a couple packages and add configuration files.

Getting Started

You’re going to need these packages:

npm i -S typescript ts-node @types/node @types/express
npm i -D ts-node-dev

After that you can create a configuration file for TypeScript with:

npx tsc -init

I don’t use the default settings, there’s a few things I change in the command above (you can also just edit tsconfig.json after it’s generated):

  • --target es6: makes TypeScript to be “compiled” into ECMAScript 6 format
  • --strict false: doesn’t enforce types as much, gives you more freedom
  • --esModuleInterop false: disables import helpers — enforces you to import packages the way they were originally meant to be imported

And the last thing you have to do is replace node with ts-node. So, on your package.json:

"start": "ts-node index.ts"

If you want to restart after changes, like you might be doing with nodemon/node-dev/supervisor/forever you can keep using them with ts-node or you could use ts-node-dev which is an optimized service for TypeScript, it compiles way faster than the others.

"dev": "ts-node-dev --poll --no-notify ./index.ts"

So let’s recap, so far you:

  • installed typescript, ts-node, ts-node-dev and types
  • generated tsconfig.json
  • added start and dev scripts

That’s all you need, now you can create .ts files instead.

Some benefits you get

Let’s dive in some of the benefits of using TypeScript.

Reduce bugs by 15%

A study revealed that static typing can prevent in average 15% of bugs².

Catching errors before you even run your app

You can annotate your code with types to catch errors during compilation time (development time if you use an editor/extension with support to TS) rather than catching errors in runtime or even in production.

Freedom / Flexibility

You can use TypeScript without types if you want. If you create a variable and don’t assign a value to it immediately it will infer the type any, which is anything.

You can choose to use TypeScript very strictly or very flexibly, tune as you like in the configuration file.

Intellisense with @types

A lot of packages come with type information, but if it doesn’t you can always try to install them with npm i @types/<package>.

TypeScript benefits on an API

TypeScript by itself already brings tons of benefits, but there are cool stuff you get when you use it in an API.

knex does support TypeScript

Good news, you can just create a knexconfig.ts and use it. All your migration/seeds can be .ts files as well.

"migrate": "knex migrate:latest --knexfile ./knexfile.ts",
"seed": "knex seed:run --knexfile ./knexfile.ts",

And you can query:

const users = await knex('users').select('*') as User[]

Migration intellisense

Types for your models

You can create interfaces for your database objects, making it easier to remember all of the columns and their names.

interface User {
  id: number
  name: string
  email: string
  address: string
  dateOfBirth: Date
  theme: 'light' | 'dark'
}

Easier to find properties on request/response

Enjoying these features?

We, at AE Studio, are working on a boilerplate project, it allows you to create a full project with frontend (React + TS) and backend (Node.js + TS). It creates a very robust real world project structure. We already used it in a few new projects and it turned out great!

We believe in the value of having a growth mindset. In sharing our work, we hope to improve upon our own practices with the help of the wider community as there’s always room for improvement. Likewise, we hope that our work brings value to you.


References

Other resources

See some more cool stuff in this five things video by Anders Hejlsberg

No one works with an agency just because they have a clever blog. To work with my colleagues, who spend their days developing software that turns your MVP into an IPO, rather than writing blog posts, click here (Then you can spend your time reading our content from your yacht / pied-a-terre). If you can’t afford to build an app, you can always learn how to succeed in tech by reading other essays.